From 8f529046a997968104aeb63880b5f27c0d35f9b8 Mon Sep 17 00:00:00 2001 From: F in Chat for Tabs Date: Sun, 1 Aug 2021 17:46:16 -0700 Subject: [PATCH] [project] Lose the battle between tabs & spaces I'm a tabs guy. I like tabs, it's an elegant way to represent indentation instead of brute-forcing it. But I have to admit that the world seems to be going towards spaces, and tooling tends not to play nice with tabs. So here we go, changing the whole repo to spaces since I'm getting tired of all the inconsistent formatting. --- src/boot/allocator.cpp | 140 ++--- src/boot/allocator.h | 68 +-- src/boot/console.cpp | 238 ++++---- src/boot/console.h | 30 +- src/boot/error.cpp | 56 +- src/boot/error.h | 8 +- src/boot/fs.cpp | 90 +-- src/boot/fs.h | 32 +- src/boot/hardware.cpp | 104 ++-- src/boot/loader.cpp | 142 ++--- src/boot/loader.h | 24 +- src/boot/main.cpp | 138 ++--- src/boot/memory.cpp | 58 +- src/boot/memory.h | 12 +- src/boot/memory_map.cpp | 394 ++++++------- src/boot/memory_map.h | 44 +- src/boot/paging.cpp | 270 ++++----- src/boot/paging.h | 28 +- src/boot/status.cpp | 318 +++++------ src/boot/status.h | 140 ++--- src/boot/support.cpp | 20 +- src/boot/video.cpp | 136 ++--- src/boot/video.h | 6 +- src/include/basic_types.h | 10 +- src/include/counted.h | 36 +- src/include/enum_bitfields.h | 38 +- src/include/init_args.h | 50 +- src/include/j6/errors.h | 24 +- src/include/j6/flags.h | 2 +- src/include/j6/init.h | 34 +- src/include/j6/signals.h | 48 +- src/include/j6/types.h | 2 +- src/include/kernel_args.h | 132 ++--- src/include/kernel_memory.h | 106 ++-- src/include/pointer_manipulation.h | 66 +-- src/kernel/acpi_tables.h | 158 +++--- src/kernel/apic.cpp | 302 +++++----- src/kernel/apic.h | 182 +++--- src/kernel/block_device.h | 2 +- src/kernel/clock.cpp | 18 +- src/kernel/clock.h | 52 +- src/kernel/console.cpp | 76 +-- src/kernel/console.h | 90 +-- src/kernel/cpprt.cpp | 26 +- src/kernel/cpu.cpp | 52 +- src/kernel/cpu.h | 38 +- src/kernel/debug.cpp | 80 +-- src/kernel/debug.h | 14 +- src/kernel/device_manager.cpp | 498 ++++++++--------- src/kernel/device_manager.h | 236 ++++---- src/kernel/frame_allocator.cpp | 194 +++---- src/kernel/frame_allocator.h | 56 +- src/kernel/gdt.cpp | 182 +++--- src/kernel/gdt.h | 82 +-- src/kernel/hpet.cpp | 112 ++-- src/kernel/hpet.h | 40 +- src/kernel/idt.cpp | 106 ++-- src/kernel/idt.h | 84 +-- src/kernel/interrupts.cpp | 126 ++--- src/kernel/interrupts.h | 10 +- src/kernel/io.cpp | 12 +- src/kernel/log.cpp | 88 +-- src/kernel/main.cpp | 364 ++++++------ src/kernel/memory_bootstrap.cpp | 208 +++---- src/kernel/msr.cpp | 14 +- src/kernel/msr.h | 44 +- src/kernel/objects/channel.cpp | 82 +-- src/kernel/objects/channel.h | 52 +- src/kernel/objects/endpoint.cpp | 146 ++--- src/kernel/objects/endpoint.h | 84 +-- src/kernel/objects/event.h | 8 +- src/kernel/objects/kobject.cpp | 46 +- src/kernel/objects/kobject.h | 114 ++-- src/kernel/objects/process.cpp | 148 ++--- src/kernel/objects/process.h | 120 ++-- src/kernel/objects/system.h | 10 +- src/kernel/objects/thread.cpp | 234 ++++---- src/kernel/objects/thread.h | 248 ++++----- src/kernel/objects/vm_area.cpp | 120 ++-- src/kernel/objects/vm_area.h | 180 +++--- src/kernel/page_table.cpp | 280 +++++----- src/kernel/page_table.h | 260 ++++----- src/kernel/page_tree.cpp | 174 +++--- src/kernel/page_tree.h | 46 +- src/kernel/panic.serial/display.h | 4 +- src/kernel/panic.serial/main.cpp | 2 +- src/kernel/panic.serial/serial.cpp | 22 +- src/kernel/panic.serial/serial.h | 10 +- src/kernel/panic.serial/symbol_table.cpp | 10 +- src/kernel/panic.serial/symbol_table.h | 24 +- src/kernel/pci.cpp | 240 ++++---- src/kernel/pci.h | 182 +++--- src/kernel/scheduler.cpp | 400 +++++++------- src/kernel/scheduler.h | 112 ++-- src/kernel/serial.cpp | 148 ++--- src/kernel/serial.h | 28 +- src/kernel/syscall.cpp | 38 +- src/kernel/syscalls/channel.cpp | 16 +- src/kernel/syscalls/endpoint.cpp | 60 +- src/kernel/syscalls/helpers.h | 34 +- src/kernel/syscalls/object.cpp | 78 +-- src/kernel/syscalls/process.cpp | 46 +- src/kernel/syscalls/system.cpp | 60 +- src/kernel/syscalls/thread.cpp | 44 +- src/kernel/syscalls/vm_area.cpp | 50 +- src/kernel/tss.cpp | 46 +- src/kernel/tss.h | 40 +- src/kernel/vm_space.cpp | 340 ++++++------ src/kernel/vm_space.h | 178 +++--- src/libraries/cpu/cpu_id.cpp | 128 ++--- src/libraries/cpu/include/cpu/cpu_id.h | 90 +-- src/libraries/elf/file.cpp | 34 +- src/libraries/elf/include/elf/file.h | 72 +-- src/libraries/elf/include/elf/headers.h | 90 +-- src/libraries/j6/init.cpp | 38 +- src/libraries/kutil/bip_buffer.cpp | 130 ++--- src/libraries/kutil/heap_allocator.cpp | 224 ++++---- src/libraries/kutil/include/kutil/avl_tree.h | 354 ++++++------ .../kutil/include/kutil/bip_buffer.h | 66 +-- .../kutil/include/kutil/constexpr_hash.h | 38 +- src/libraries/kutil/include/kutil/coord.h | 8 +- src/libraries/kutil/include/kutil/guid.h | 20 +- src/libraries/kutil/include/kutil/hash.h | 30 +- .../kutil/include/kutil/heap_allocator.h | 72 +-- .../kutil/include/kutil/linked_list.h | 522 +++++++++--------- src/libraries/kutil/include/kutil/logger.h | 152 ++--- src/libraries/kutil/include/kutil/map.h | 378 ++++++------- src/libraries/kutil/include/kutil/memory.h | 6 +- src/libraries/kutil/include/kutil/misc.h | 4 +- .../kutil/include/kutil/no_construct.h | 6 +- .../kutil/include/kutil/slab_allocated.h | 44 +- src/libraries/kutil/include/kutil/spinlock.h | 38 +- src/libraries/kutil/include/kutil/util.h | 6 +- src/libraries/kutil/include/kutil/vector.h | 464 ++++++++-------- src/libraries/kutil/logger.cpp | 178 +++--- src/libraries/kutil/memory.cpp | 24 +- src/libraries/kutil/spinlock.cpp | 44 +- src/libraries/libc/tests/_PDCLIB_test.h | 62 +-- src/libraries/libc/tests/printf_testcases.h | 4 +- src/libraries/libc/tests/scanf_testcases.h | 4 +- src/tests/constexpr_hash.cpp | 20 +- src/tests/container_helpers.h | 10 +- src/tests/heap_allocator.cpp | 252 ++++----- src/tests/linked_list.cpp | 174 +++--- src/tests/logger.cpp | 24 +- src/tests/main.cpp | 18 +- src/tests/map.cpp | 126 ++--- src/tests/vector.cpp | 28 +- src/user/drv.uefi_fb/font.cpp | 82 +-- src/user/drv.uefi_fb/font.h | 38 +- src/user/drv.uefi_fb/main.cpp | 182 +++--- src/user/drv.uefi_fb/screen.cpp | 50 +- src/user/drv.uefi_fb/screen.h | 36 +- src/user/drv.uefi_fb/scrollback.cpp | 56 +- src/user/drv.uefi_fb/scrollback.h | 18 +- src/user/srv.init/main.cpp | 8 +- src/user/srv.init/modules.cpp | 68 +-- src/user/testapp/io.cpp | 12 +- src/user/testapp/main.cpp | 180 +++--- src/user/testapp/serial.cpp | 32 +- src/user/testapp/serial.h | 18 +- 161 files changed, 7958 insertions(+), 7958 deletions(-) diff --git a/src/boot/allocator.cpp b/src/boot/allocator.cpp index 41f6d39..8d5f47e 100644 --- a/src/boot/allocator.cpp +++ b/src/boot/allocator.cpp @@ -24,139 +24,139 @@ static_assert(sizeof(allocation_register) == page_size); void allocator::init( - allocation_register *&allocs, - modules_page *&modules, - uefi::boot_services *bs) + allocation_register *&allocs, + modules_page *&modules, + uefi::boot_services *bs) { - new (&g_alloc) allocator(*bs); - allocs = g_alloc.m_register; - modules = g_alloc.m_modules; + new (&g_alloc) allocator(*bs); + allocs = g_alloc.m_register; + modules = g_alloc.m_modules; } allocator::allocator(uefi::boot_services &bs) : - m_bs(bs), - m_register(nullptr), - m_modules(nullptr) + m_bs(bs), + m_register(nullptr), + m_modules(nullptr) { - add_register(); - add_modules(); + add_register(); + add_modules(); } void allocator::add_register() { - allocation_register *reg = nullptr; + allocation_register *reg = nullptr; - try_or_raise( - m_bs.allocate_pages(uefi::allocate_type::any_pages, - uefi::memory_type::loader_data, 1, reinterpret_cast(®)), - L"Failed allocating allocation register page"); + try_or_raise( + m_bs.allocate_pages(uefi::allocate_type::any_pages, + uefi::memory_type::loader_data, 1, reinterpret_cast(®)), + L"Failed allocating allocation register page"); - m_bs.set_mem(reg, sizeof(allocation_register), 0); + m_bs.set_mem(reg, sizeof(allocation_register), 0); - if (m_register) - m_register->next = reg; + if (m_register) + m_register->next = reg; - m_register = reg; - return; + m_register = reg; + return; } void allocator::add_modules() { - modules_page *mods = reinterpret_cast( - allocate_pages(1, alloc_type::init_args, true)); + modules_page *mods = reinterpret_cast( + allocate_pages(1, alloc_type::init_args, true)); - if (m_modules) - m_modules->next = reinterpret_cast(mods); + if (m_modules) + m_modules->next = reinterpret_cast(mods); - mods->modules = reinterpret_cast(mods + 1); - m_modules = mods; - m_next_mod = mods->modules; - return; + mods->modules = reinterpret_cast(mods + 1); + m_modules = mods; + m_next_mod = mods->modules; + return; } void * allocator::allocate_pages(size_t count, alloc_type type, bool zero) { - if (count & ~0xffffffffull) { - error::raise(uefi::status::unsupported, - L"Cannot allocate more than 16TiB in pages at once.", - __LINE__); - } + if (count & ~0xffffffffull) { + error::raise(uefi::status::unsupported, + L"Cannot allocate more than 16TiB in pages at once.", + __LINE__); + } - if (!m_register || m_register->count == 0xff) - add_register(); + if (!m_register || m_register->count == 0xff) + add_register(); - void *pages = nullptr; + void *pages = nullptr; - try_or_raise( - m_bs.allocate_pages(uefi::allocate_type::any_pages, - uefi::memory_type::loader_data, count, &pages), - L"Failed allocating usable pages"); + try_or_raise( + m_bs.allocate_pages(uefi::allocate_type::any_pages, + uefi::memory_type::loader_data, count, &pages), + L"Failed allocating usable pages"); - page_allocation &ent = m_register->entries[m_register->count++]; - ent.address = reinterpret_cast(pages); - ent.count = count; - ent.type = type; + page_allocation &ent = m_register->entries[m_register->count++]; + ent.address = reinterpret_cast(pages); + ent.count = count; + ent.type = type; - if (zero) - m_bs.set_mem(pages, count * page_size, 0); + if (zero) + m_bs.set_mem(pages, count * page_size, 0); - return pages; + return pages; } module * allocator::allocate_module_untyped(size_t size) { - size_t remaining = - reinterpret_cast(m_modules) + page_size - - reinterpret_cast(m_next_mod); + size_t remaining = + reinterpret_cast(m_modules) + page_size + - reinterpret_cast(m_next_mod); - if (size > remaining) - add_modules(); + if (size > remaining) + add_modules(); - ++m_modules->count; - module *m = m_next_mod; - m_next_mod = offset_ptr(m_next_mod, size); + ++m_modules->count; + module *m = m_next_mod; + m_next_mod = offset_ptr(m_next_mod, size); - m->mod_length = size; - return m; + m->mod_length = size; + return m; } void * allocator::allocate(size_t size, bool zero) { - void *p = nullptr; - try_or_raise( - m_bs.allocate_pool(uefi::memory_type::loader_data, size, &p), - L"Could not allocate pool memory"); + void *p = nullptr; + try_or_raise( + m_bs.allocate_pool(uefi::memory_type::loader_data, size, &p), + L"Could not allocate pool memory"); - if (zero) - m_bs.set_mem(p, size, 0); + if (zero) + m_bs.set_mem(p, size, 0); - return p; + return p; } void allocator::free(void *p) { - try_or_raise( - m_bs.free_pool(p), - L"Freeing pool memory"); + try_or_raise( + m_bs.free_pool(p), + L"Freeing pool memory"); } void allocator::memset(void *start, size_t size, uint8_t value) { - m_bs.set_mem(start, size, value); + m_bs.set_mem(start, size, value); } void allocator::copy(void *to, void *from, size_t size) { - m_bs.copy_mem(to, from, size); + m_bs.copy_mem(to, from, size); } } // namespace memory diff --git a/src/boot/allocator.h b/src/boot/allocator.h index 8b2ce1e..45c9fc2 100644 --- a/src/boot/allocator.h +++ b/src/boot/allocator.h @@ -3,15 +3,15 @@ /// Page allocator class definition namespace uefi { - class boot_services; + class boot_services; } namespace kernel { namespace init { - enum class allocation_type : uint8_t; - struct allocation_register; - struct module; - struct modules_page; + enum class allocation_type : uint8_t; + struct allocation_register; + struct module; + struct modules_page; }} namespace boot { @@ -22,46 +22,46 @@ using alloc_type = kernel::init::allocation_type; class allocator { public: - using allocation_register = kernel::init::allocation_register; - using module = kernel::init::module; - using modules_page = kernel::init::modules_page; + using allocation_register = kernel::init::allocation_register; + using module = kernel::init::module; + using modules_page = kernel::init::modules_page; - allocator(uefi::boot_services &bs); + allocator(uefi::boot_services &bs); - void * allocate(size_t size, bool zero = false); - void free(void *p); + void * allocate(size_t size, bool zero = false); + void free(void *p); - void * allocate_pages(size_t count, alloc_type type, bool zero = false); + void * allocate_pages(size_t count, alloc_type type, bool zero = false); - template - M * allocate_module(size_t extra = 0) { - return static_cast(allocate_module_untyped(sizeof(M) + extra)); - } + template + M * allocate_module(size_t extra = 0) { + return static_cast(allocate_module_untyped(sizeof(M) + extra)); + } - void memset(void *start, size_t size, uint8_t value); - void copy(void *to, void *from, size_t size); + void memset(void *start, size_t size, uint8_t value); + void copy(void *to, void *from, size_t size); - inline void zero(void *start, size_t size) { memset(start, size, 0); } + inline void zero(void *start, size_t size) { memset(start, size, 0); } - /// Initialize the global allocator - /// \arg allocs [out] Poiinter to the initial allocation register - /// \arg modules [out] Pointer to the initial modules_page - /// \arg bs UEFI boot services - static void init( - allocation_register *&allocs, - modules_page *&modules, - uefi::boot_services *bs); + /// Initialize the global allocator + /// \arg allocs [out] Poiinter to the initial allocation register + /// \arg modules [out] Pointer to the initial modules_page + /// \arg bs UEFI boot services + static void init( + allocation_register *&allocs, + modules_page *&modules, + uefi::boot_services *bs); private: - void add_register(); - void add_modules(); - module * allocate_module_untyped(size_t size); + void add_register(); + void add_modules(); + module * allocate_module_untyped(size_t size); - uefi::boot_services &m_bs; + uefi::boot_services &m_bs; - allocation_register *m_register; - modules_page *m_modules; - module *m_next_mod; + allocation_register *m_register; + modules_page *m_modules; + module *m_next_mod; }; } // namespace memory diff --git a/src/boot/console.cpp b/src/boot/console.cpp index 14e8e0e..b0f0c77 100644 --- a/src/boot/console.cpp +++ b/src/boot/console.cpp @@ -19,195 +19,195 @@ size_t COLS = 0; console *console::s_console = nullptr; static const wchar_t digits[] = {u'0', u'1', u'2', u'3', u'4', u'5', - u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'}; + u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'}; size_t wstrlen(const wchar_t *s) { - size_t count = 0; - while (s && *s++) count++; - return count; + size_t count = 0; + while (s && *s++) count++; + return count; } console::console(uefi::protos::simple_text_output *out) : - m_rows {0}, - m_cols {0}, - m_out {out} + m_rows {0}, + m_cols {0}, + m_out {out} { - try_or_raise( - m_out->query_mode(m_out->mode->mode, &m_cols, &m_rows), - L"Failed to get text output mode."); - try_or_raise( - m_out->clear_screen(), - L"Failed to clear screen"); - s_console = this; + try_or_raise( + m_out->query_mode(m_out->mode->mode, &m_cols, &m_rows), + L"Failed to get text output mode."); + try_or_raise( + m_out->clear_screen(), + L"Failed to clear screen"); + s_console = this; } void console::announce() { - m_out->set_attribute(uefi::attribute::light_cyan); - m_out->output_string(L"jsix loader "); + m_out->set_attribute(uefi::attribute::light_cyan); + m_out->output_string(L"jsix loader "); - m_out->set_attribute(uefi::attribute::light_magenta); - m_out->output_string(GIT_VERSION_WIDE); + m_out->set_attribute(uefi::attribute::light_magenta); + m_out->output_string(GIT_VERSION_WIDE); - m_out->set_attribute(uefi::attribute::light_gray); - m_out->output_string(L" booting...\r\n"); + m_out->set_attribute(uefi::attribute::light_gray); + m_out->output_string(L" booting...\r\n"); } size_t console::print_hex(uint32_t n) const { - wchar_t buffer[9]; - wchar_t *p = buffer; - for (int i = 7; i >= 0; --i) { - uint8_t nibble = (n >> (i*4)) & 0xf; - *p++ = digits[nibble]; - } - *p = 0; - m_out->output_string(buffer); - return 8; + wchar_t buffer[9]; + wchar_t *p = buffer; + for (int i = 7; i >= 0; --i) { + uint8_t nibble = (n >> (i*4)) & 0xf; + *p++ = digits[nibble]; + } + *p = 0; + m_out->output_string(buffer); + return 8; } size_t console::print_long_hex(uint64_t n) const { - wchar_t buffer[17]; - wchar_t *p = buffer; - for (int i = 15; i >= 0; --i) { - uint8_t nibble = (n >> (i*4)) & 0xf; - *p++ = digits[nibble]; - } - *p = 0; - m_out->output_string(buffer); - return 16; + wchar_t buffer[17]; + wchar_t *p = buffer; + for (int i = 15; i >= 0; --i) { + uint8_t nibble = (n >> (i*4)) & 0xf; + *p++ = digits[nibble]; + } + *p = 0; + m_out->output_string(buffer); + return 16; } size_t console::print_dec(uint32_t n) const { - wchar_t buffer[11]; - wchar_t *p = buffer + 10; - *p-- = 0; - do { - *p-- = digits[n % 10]; - n /= 10; - } while (n != 0); + wchar_t buffer[11]; + wchar_t *p = buffer + 10; + *p-- = 0; + do { + *p-- = digits[n % 10]; + n /= 10; + } while (n != 0); - m_out->output_string(++p); - return 10 - (p - buffer); + m_out->output_string(++p); + return 10 - (p - buffer); } size_t console::print_long_dec(uint64_t n) const { - wchar_t buffer[21]; - wchar_t *p = buffer + 20; - *p-- = 0; - do { - *p-- = digits[n % 10]; - n /= 10; - } while (n != 0); + wchar_t buffer[21]; + wchar_t *p = buffer + 20; + *p-- = 0; + do { + *p-- = digits[n % 10]; + n /= 10; + } while (n != 0); - m_out->output_string(++p); - return 20 - (p - buffer); + m_out->output_string(++p); + return 20 - (p - buffer); } size_t console::vprintf(const wchar_t *fmt, va_list args) const { - wchar_t buffer[256]; - const wchar_t *r = fmt; - wchar_t *w = buffer; - size_t count = 0; + wchar_t buffer[256]; + const wchar_t *r = fmt; + wchar_t *w = buffer; + size_t count = 0; - while (r && *r) { - if (*r != L'%') { - count++; - *w++ = *r++; - continue; - } + while (r && *r) { + if (*r != L'%') { + count++; + *w++ = *r++; + continue; + } - *w = 0; - m_out->output_string(buffer); - w = buffer; + *w = 0; + m_out->output_string(buffer); + w = buffer; - r++; // chomp the % + r++; // chomp the % - switch (*r++) { - case L'%': - m_out->output_string(const_cast(L"%")); - count++; - break; + switch (*r++) { + case L'%': + m_out->output_string(const_cast(L"%")); + count++; + break; - case L'x': - count += print_hex(va_arg(args, uint32_t)); - break; + case L'x': + count += print_hex(va_arg(args, uint32_t)); + break; - case L'd': - case L'u': - count += print_dec(va_arg(args, uint32_t)); - break; + case L'd': + case L'u': + count += print_dec(va_arg(args, uint32_t)); + break; - case L's': - { - wchar_t *s = va_arg(args, wchar_t*); - count += wstrlen(s); - m_out->output_string(s); - } - break; + case L's': + { + wchar_t *s = va_arg(args, wchar_t*); + count += wstrlen(s); + m_out->output_string(s); + } + break; - case L'l': - switch (*r++) { - case L'x': - count += print_long_hex(va_arg(args, uint64_t)); - break; + case L'l': + switch (*r++) { + case L'x': + count += print_long_hex(va_arg(args, uint64_t)); + break; - case L'd': - case L'u': - count += print_long_dec(va_arg(args, uint64_t)); - break; + case L'd': + case L'u': + count += print_long_dec(va_arg(args, uint64_t)); + break; - default: - break; - } - break; + default: + break; + } + break; - default: - break; - } - } + default: + break; + } + } - *w = 0; - m_out->output_string(buffer); - return count; + *w = 0; + m_out->output_string(buffer); + return count; } size_t console::printf(const wchar_t *fmt, ...) const { - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); - size_t result = vprintf(fmt, args); + size_t result = vprintf(fmt, args); - va_end(args); - return result; + va_end(args); + return result; } size_t console::print(const wchar_t *fmt, ...) { - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); - size_t result = get().vprintf(fmt, args); + size_t result = get().vprintf(fmt, args); - va_end(args); - return result; + va_end(args); + return result; } } // namespace boot diff --git a/src/boot/console.h b/src/boot/console.h index 9012d45..7411dce 100644 --- a/src/boot/console.h +++ b/src/boot/console.h @@ -8,7 +8,7 @@ namespace uefi { namespace protos { - struct simple_text_output; + struct simple_text_output; }} namespace boot { @@ -17,28 +17,28 @@ namespace boot { class console { public: - console(uefi::protos::simple_text_output *out); + console(uefi::protos::simple_text_output *out); - void announce(); + void announce(); - size_t print_hex(uint32_t n) const; - size_t print_dec(uint32_t n) const; - size_t print_long_hex(uint64_t n) const; - size_t print_long_dec(uint64_t n) const; - size_t printf(const wchar_t *fmt, ...) const; + size_t print_hex(uint32_t n) const; + size_t print_dec(uint32_t n) const; + size_t print_long_hex(uint64_t n) const; + size_t print_long_dec(uint64_t n) const; + size_t printf(const wchar_t *fmt, ...) const; - static console & get() { return *s_console; } - static size_t print(const wchar_t *fmt, ...); + static console & get() { return *s_console; } + static size_t print(const wchar_t *fmt, ...); private: - friend class status_line; + friend class status_line; - size_t vprintf(const wchar_t *fmt, va_list args) const; + size_t vprintf(const wchar_t *fmt, va_list args) const; - size_t m_rows, m_cols; - uefi::protos::simple_text_output *m_out; + size_t m_rows, m_cols; + uefi::protos::simple_text_output *m_out; - static console *s_console; + static console *s_console; }; size_t wstrlen(const wchar_t *s); diff --git a/src/boot/error.cpp b/src/boot/error.cpp index 3af8f9b..68fccb1 100644 --- a/src/boot/error.cpp +++ b/src/boot/error.cpp @@ -7,8 +7,8 @@ namespace boot { namespace error { struct error_code_desc { - uefi::status code; - const wchar_t *name; + uefi::status code; + const wchar_t *name; }; struct error_code_desc error_table[] = { @@ -17,46 +17,46 @@ struct error_code_desc error_table[] = { #include "uefi/errors.inc" #undef STATUS_ERROR #undef STATUS_WARNING - { uefi::status::success, nullptr } + { uefi::status::success, nullptr } }; const wchar_t * message(uefi::status status) { - int32_t i = -1; - while (error_table[++i].name != nullptr) { - if (error_table[i].code == status) return error_table[i].name; - } + int32_t i = -1; + while (error_table[++i].name != nullptr) { + if (error_table[i].code == status) return error_table[i].name; + } - if (uefi::is_error(status)) - return L"Unknown Error"; - else - return L"Unknown Warning"; + if (uefi::is_error(status)) + return L"Unknown Error"; + else + return L"Unknown Warning"; } [[ noreturn ]] static void cpu_assert(uefi::status s, const wchar_t *message, size_t line) { - asm volatile ( - "movq $0xeeeeeeebadbadbad, %%r8;" - "movq %0, %%r9;" - "movq %1, %%r10;" - "movq %2, %%r11;" - "movq $0, %%rdx;" - "divq %%rdx;" - : - : "r"((uint64_t)s), "r"(message), "r"(line) - : "rax", "rdx", "r8", "r9", "r10"); - while (1) asm("hlt"); + asm volatile ( + "movq $0xeeeeeeebadbadbad, %%r8;" + "movq %0, %%r9;" + "movq %1, %%r10;" + "movq %2, %%r11;" + "movq $0, %%rdx;" + "divq %%rdx;" + : + : "r"((uint64_t)s), "r"(message), "r"(line) + : "rax", "rdx", "r8", "r9", "r10"); + while (1) asm("hlt"); } [[ noreturn ]] void raise(uefi::status status, const wchar_t *message, size_t line) { - if(status_line::fail(message, status)) - while (1) asm("hlt"); - else - cpu_assert(status, message, line); + if(status_line::fail(message, status)) + while (1) asm("hlt"); + else + cpu_assert(status, message, line); } @@ -65,6 +65,6 @@ raise(uefi::status status, const wchar_t *message, size_t line) void debug_break() { - volatile int go = 0; - while (!go); + volatile int go = 0; + while (!go); } diff --git a/src/boot/error.h b/src/boot/error.h index 6ce90ad..c2b5d57 100644 --- a/src/boot/error.h +++ b/src/boot/error.h @@ -26,8 +26,8 @@ void debug_break(); /// \arg s An expression evaluating to a UEFI status /// \arg m The error message to use on failure #define try_or_raise(s, m) \ - do { \ - uefi::status _s = (s); \ - if (uefi::is_error(_s)) ::boot::error::raise(_s, (m), __LINE__); \ - } while(0) + do { \ + uefi::status _s = (s); \ + if (uefi::is_error(_s)) ::boot::error::raise(_s, (m), __LINE__); \ + } while(0) diff --git a/src/boot/fs.cpp b/src/boot/fs.cpp index 4b6f1e0..a3146b2 100644 --- a/src/boot/fs.cpp +++ b/src/boot/fs.cpp @@ -19,91 +19,91 @@ namespace fs { using memory::alloc_type; file::file(uefi::protos::file *f) : - m_file(f) + m_file(f) { } file::file(file &o) : - m_file(o.m_file) + m_file(o.m_file) { - o.m_file = nullptr; + o.m_file = nullptr; } file::file(file &&o) : - m_file(o.m_file) + m_file(o.m_file) { - o.m_file = nullptr; + o.m_file = nullptr; } file::~file() { - if (m_file) - m_file->close(); + if (m_file) + m_file->close(); } file file::open(const wchar_t *path) { - uefi::protos::file *fh = nullptr; + uefi::protos::file *fh = nullptr; - try_or_raise( - m_file->open(&fh, path, uefi::file_mode::read, uefi::file_attr::none), - L"Could not open relative path to file"); + try_or_raise( + m_file->open(&fh, path, uefi::file_mode::read, uefi::file_attr::none), + L"Could not open relative path to file"); - return file(fh); + return file(fh); } buffer file::load() { - uint8_t info_buf[sizeof(uefi::protos::file_info) + 100]; - size_t size = sizeof(info_buf); - uefi::guid info_guid = uefi::protos::file_info::guid; + uint8_t info_buf[sizeof(uefi::protos::file_info) + 100]; + size_t size = sizeof(info_buf); + uefi::guid info_guid = uefi::protos::file_info::guid; - try_or_raise( - m_file->get_info(&info_guid, &size, &info_buf), - L"Could not get file info"); + try_or_raise( + m_file->get_info(&info_guid, &size, &info_buf), + L"Could not get file info"); - uefi::protos::file_info *info = - reinterpret_cast(&info_buf); + uefi::protos::file_info *info = + reinterpret_cast(&info_buf); - size_t pages = memory::bytes_to_pages(info->file_size); - void *data = g_alloc.allocate_pages(pages, alloc_type::file); + size_t pages = memory::bytes_to_pages(info->file_size); + void *data = g_alloc.allocate_pages(pages, alloc_type::file); - size = info->file_size; - try_or_raise( - m_file->read(&size, data), - L"Could not read from file"); + size = info->file_size; + try_or_raise( + m_file->read(&size, data), + L"Could not read from file"); - return { .pointer = data, .count = size }; + return { .pointer = data, .count = size }; } file get_boot_volume(uefi::handle image, uefi::boot_services *bs) { - status_line status(L"Looking up boot volume"); + status_line status(L"Looking up boot volume"); - const uefi::guid le_guid = uefi::protos::loaded_image::guid; - uefi::protos::loaded_image *loaded_image = nullptr; + const uefi::guid le_guid = uefi::protos::loaded_image::guid; + uefi::protos::loaded_image *loaded_image = nullptr; - try_or_raise( - bs->handle_protocol(image, &le_guid, - reinterpret_cast(&loaded_image)), - L"Could not find currently running UEFI loaded image"); + try_or_raise( + bs->handle_protocol(image, &le_guid, + reinterpret_cast(&loaded_image)), + L"Could not find currently running UEFI loaded image"); - const uefi::guid sfs_guid = uefi::protos::simple_file_system::guid; - uefi::protos::simple_file_system *fs; - try_or_raise( - bs->handle_protocol(loaded_image->device_handle, &sfs_guid, - reinterpret_cast(&fs)), - L"Could not find filesystem protocol for boot volume"); + const uefi::guid sfs_guid = uefi::protos::simple_file_system::guid; + uefi::protos::simple_file_system *fs; + try_or_raise( + bs->handle_protocol(loaded_image->device_handle, &sfs_guid, + reinterpret_cast(&fs)), + L"Could not find filesystem protocol for boot volume"); - uefi::protos::file *f; - try_or_raise( - fs->open_volume(&f), - L"Could not open the boot volume"); + uefi::protos::file *f; + try_or_raise( + fs->open_volume(&f), + L"Could not open the boot volume"); - return file(f); + return file(f); } } // namespace fs diff --git a/src/boot/fs.h b/src/boot/fs.h index 06a99ff..f183b94 100644 --- a/src/boot/fs.h +++ b/src/boot/fs.h @@ -6,9 +6,9 @@ #include "counted.h" namespace uefi { - struct boot_services; + struct boot_services; namespace protos { - struct file; + struct file; }} namespace boot { @@ -18,26 +18,26 @@ namespace fs { class file { public: - file(file &&o); - file(file &o); - ~file(); + file(file &&o); + file(file &o); + ~file(); - /// Open another file or directory, relative to this one. - /// \arg path Relative path to the target file from this one - file open(const wchar_t *path); + /// Open another file or directory, relative to this one. + /// \arg path Relative path to the target file from this one + file open(const wchar_t *path); - /// Load the contents of this file into memory. - /// \returns A buffer describing the loaded memory. The - /// memory will be page-aligned. - buffer load(); + /// Load the contents of this file into memory. + /// \returns A buffer describing the loaded memory. The + /// memory will be page-aligned. + buffer load(); private: - friend file get_boot_volume(uefi::handle, uefi::boot_services*); + friend file get_boot_volume(uefi::handle, uefi::boot_services*); - file(uefi::protos::file *f); + file(uefi::protos::file *f); - uefi::protos::file *m_file; - uefi::boot_services *m_bs; + uefi::protos::file *m_file; + uefi::boot_services *m_bs; }; /// Get the filesystem this loader was loaded from. diff --git a/src/boot/hardware.cpp b/src/boot/hardware.cpp index f6eb0c3..83bbea7 100644 --- a/src/boot/hardware.cpp +++ b/src/boot/hardware.cpp @@ -10,92 +10,92 @@ namespace hw { void * find_acpi_table(uefi::system_table *st) { - status_line status(L"Searching for ACPI table"); + status_line status(L"Searching for ACPI table"); - // Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found. - uintptr_t acpi1_table = 0; + // Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found. + uintptr_t acpi1_table = 0; - for (size_t i = 0; i < st->number_of_table_entries; ++i) { - uefi::configuration_table *table = &st->configuration_table[i]; + for (size_t i = 0; i < st->number_of_table_entries; ++i) { + uefi::configuration_table *table = &st->configuration_table[i]; - // If we find an ACPI 2.0 table, return it immediately - if (table->vendor_guid == uefi::vendor_guids::acpi2) - return table->vendor_table; + // If we find an ACPI 2.0 table, return it immediately + if (table->vendor_guid == uefi::vendor_guids::acpi2) + return table->vendor_table; - if (table->vendor_guid == uefi::vendor_guids::acpi1) { - // Mark a v1 table with the LSB high - acpi1_table = reinterpret_cast(table->vendor_table); - acpi1_table |= 1; - } - } + if (table->vendor_guid == uefi::vendor_guids::acpi1) { + // Mark a v1 table with the LSB high + acpi1_table = reinterpret_cast(table->vendor_table); + acpi1_table |= 1; + } + } - if (!acpi1_table) { - error::raise(uefi::status::not_found, L"Could not find ACPI table"); - } else if (acpi1_table & 1) { - status_line::warn(L"Only found ACPI 1.0 table"); - } + if (!acpi1_table) { + error::raise(uefi::status::not_found, L"Could not find ACPI table"); + } else if (acpi1_table & 1) { + status_line::warn(L"Only found ACPI 1.0 table"); + } - return reinterpret_cast(acpi1_table); + return reinterpret_cast(acpi1_table); } static uint64_t rdmsr(uint32_t addr) { - uint32_t low, high; - __asm__ __volatile__ ("rdmsr" : "=a"(low), "=d"(high) : "c"(addr)); - return (static_cast(high) << 32) | low; + uint32_t low, high; + __asm__ __volatile__ ("rdmsr" : "=a"(low), "=d"(high) : "c"(addr)); + return (static_cast(high) << 32) | low; } static void wrmsr(uint32_t addr, uint64_t value) { - uint32_t low = value & 0xffffffff; - uint32_t high = value >> 32; - __asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high)); + uint32_t low = value & 0xffffffff; + uint32_t high = value >> 32; + __asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high)); } void setup_control_regs() { - uint64_t cr4 = 0; - asm volatile ( "mov %%cr4, %0" : "=r" (cr4) ); - cr4 |= - 0x000080 | // Enable global pages - 0x000200 | // Enable FXSAVE/FXRSTOR - 0x010000 | // Enable FSGSBASE - 0x020000 | // Enable PCIDs - 0; - asm volatile ( "mov %0, %%cr4" :: "r" (cr4) ); + uint64_t cr4 = 0; + asm volatile ( "mov %%cr4, %0" : "=r" (cr4) ); + cr4 |= + 0x000080 | // Enable global pages + 0x000200 | // Enable FXSAVE/FXRSTOR + 0x010000 | // Enable FSGSBASE + 0x020000 | // Enable PCIDs + 0; + asm volatile ( "mov %0, %%cr4" :: "r" (cr4) ); - // Set up IA32_EFER - constexpr uint32_t IA32_EFER = 0xC0000080; - uint64_t efer = rdmsr(IA32_EFER); - efer |= - 0x0001 | // Enable SYSCALL - 0x0800 | // Enable NX bit - 0; - wrmsr(IA32_EFER, efer); + // Set up IA32_EFER + constexpr uint32_t IA32_EFER = 0xC0000080; + uint64_t efer = rdmsr(IA32_EFER); + efer |= + 0x0001 | // Enable SYSCALL + 0x0800 | // Enable NX bit + 0; + wrmsr(IA32_EFER, efer); } void check_cpu_supported() { - status_line status {L"Checking CPU features"}; + status_line status {L"Checking CPU features"}; - cpu::cpu_id cpu; - uint64_t missing = cpu.missing(); - if (missing) { + cpu::cpu_id cpu; + uint64_t missing = cpu.missing(); + if (missing) { #define CPU_FEATURE_OPT(...) #define CPU_FEATURE_REQ(name, ...) \ - if (!cpu.has_feature(cpu::feature::name)) { \ - status::fail(L"CPU required feature " L ## #name, uefi::status::unsupported); \ - } + if (!cpu.has_feature(cpu::feature::name)) { \ + status::fail(L"CPU required feature " L ## #name, uefi::status::unsupported); \ + } #include "cpu/features.inc" #undef CPU_FEATURE_REQ #undef CPU_FEATURE_OPT - error::raise(uefi::status::unsupported, L"CPU not supported"); - } + error::raise(uefi::status::unsupported, L"CPU not supported"); + } } diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index aaec5f5..7c773c7 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -23,108 +23,108 @@ using memory::alloc_type; buffer load_file( - fs::file &disk, - const program_desc &desc) + fs::file &disk, + const program_desc &desc) { - status_line status(L"Loading file", desc.path); + status_line status(L"Loading file", desc.path); - fs::file file = disk.open(desc.path); - buffer b = file.load(); + fs::file file = disk.open(desc.path); + buffer b = file.load(); - //console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size); - return b; + //console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size); + return b; } static void create_module(buffer data, const program_desc &desc, bool loaded) { - size_t path_len = wstrlen(desc.path); - init::module_program *mod = g_alloc.allocate_module(path_len); - mod->mod_type = init::module_type::program; - mod->base_address = reinterpret_cast(data.pointer); - if (loaded) - mod->mod_flags = static_cast( - static_cast(mod->mod_flags) | - static_cast(init::module_flags::no_load)); + size_t path_len = wstrlen(desc.path); + init::module_program *mod = g_alloc.allocate_module(path_len); + mod->mod_type = init::module_type::program; + mod->base_address = reinterpret_cast(data.pointer); + if (loaded) + mod->mod_flags = static_cast( + static_cast(mod->mod_flags) | + static_cast(init::module_flags::no_load)); - // TODO: support non-ascii path characters and do real utf-16 to utf-8 - // conversion - for (int i = 0; i < path_len; ++i) - mod->filename[i] = desc.path[i]; - mod->filename[path_len] = 0; + // TODO: support non-ascii path characters and do real utf-16 to utf-8 + // conversion + for (int i = 0; i < path_len; ++i) + mod->filename[i] = desc.path[i]; + mod->filename[path_len] = 0; } init::program * load_program( - fs::file &disk, - const program_desc &desc, - bool add_module) + fs::file &disk, + const program_desc &desc, + bool add_module) { - status_line status(L"Loading program", desc.name); + status_line status(L"Loading program", desc.name); - buffer data = load_file(disk, desc); + buffer data = load_file(disk, desc); - if (add_module) - create_module(data, desc, true); + if (add_module) + create_module(data, desc, true); - elf::file program(data.pointer, data.count); - if (!program.valid()) - error::raise(uefi::status::load_error, L"ELF file not valid"); + elf::file program(data.pointer, data.count); + if (!program.valid()) + error::raise(uefi::status::load_error, L"ELF file not valid"); - size_t num_sections = 0; - for (auto &seg : program.programs()) { - if (seg.type == elf::segment_type::load) - ++num_sections; - } + size_t num_sections = 0; + for (auto &seg : program.programs()) { + if (seg.type == elf::segment_type::load) + ++num_sections; + } - init::program_section *sections = new init::program_section [num_sections]; + init::program_section *sections = new init::program_section [num_sections]; - size_t next_section = 0; - for (auto &seg : program.programs()) { - if (seg.type != elf::segment_type::load) - continue; + size_t next_section = 0; + for (auto &seg : program.programs()) { + if (seg.type != elf::segment_type::load) + continue; - init::program_section §ion = sections[next_section++]; + init::program_section §ion = sections[next_section++]; - size_t page_count = memory::bytes_to_pages(seg.mem_size); + size_t page_count = memory::bytes_to_pages(seg.mem_size); - if (seg.mem_size > seg.file_size) { - void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true); - void *source = offset_ptr(data.pointer, seg.offset); - g_alloc.copy(pages, source, seg.file_size); - section.phys_addr = reinterpret_cast(pages); - } else { - section.phys_addr = program.base() + seg.offset; - } + if (seg.mem_size > seg.file_size) { + void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true); + void *source = offset_ptr(data.pointer, seg.offset); + g_alloc.copy(pages, source, seg.file_size); + section.phys_addr = reinterpret_cast(pages); + } else { + section.phys_addr = program.base() + seg.offset; + } - section.virt_addr = seg.vaddr; - section.size = seg.mem_size; - section.type = static_cast(seg.flags); - } + section.virt_addr = seg.vaddr; + section.size = seg.mem_size; + section.type = static_cast(seg.flags); + } - init::program *prog = new init::program; - prog->sections = { .pointer = sections, .count = num_sections }; - prog->phys_base = program.base(); - prog->entrypoint = program.entrypoint(); - return prog; + init::program *prog = new init::program; + prog->sections = { .pointer = sections, .count = num_sections }; + prog->phys_base = program.base(); + prog->entrypoint = program.entrypoint(); + return prog; } void load_module( - fs::file &disk, - const program_desc &desc) + fs::file &disk, + const program_desc &desc) { - status_line status(L"Loading module", desc.name); + status_line status(L"Loading module", desc.name); - buffer data = load_file(disk, desc); - create_module(data, desc, false); + buffer data = load_file(disk, desc); + create_module(data, desc, false); } void verify_kernel_header(init::program &program) { - status_line status(L"Verifying kernel header"); + status_line status(L"Verifying kernel header"); const init::header *header = reinterpret_cast(program.sections[0].phys_addr); @@ -138,15 +138,15 @@ verify_kernel_header(init::program &program) if (header->version < init::min_header_version) error::raise(uefi::status::unsupported, L"Kernel header version not supported"); - console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n", + console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n", header->version_major, header->version_minor, header->version_patch, header->version_gitsha); - /* - for (auto §ion : program.sections) - console::print(L" Section: p:0x%lx v:0x%lx fs:0x%x ms:0x%x\r\n", - section.phys_addr, section.virt_addr, section.file_size, section.mem_size); - */ + /* + for (auto §ion : program.sections) + console::print(L" Section: p:0x%lx v:0x%lx fs:0x%x ms:0x%x\r\n", + section.phys_addr, section.virt_addr, section.file_size, section.mem_size); + */ } } // namespace loader diff --git a/src/boot/loader.h b/src/boot/loader.h index 625062b..0baeaba 100644 --- a/src/boot/loader.h +++ b/src/boot/loader.h @@ -6,22 +6,22 @@ namespace kernel { namespace init { - struct program; - struct module; + struct program; + struct module; }} namespace boot { namespace fs { - class file; + class file; } namespace loader { struct program_desc { - const wchar_t *name; - const wchar_t *path; + const wchar_t *name; + const wchar_t *path; }; /// Load a file from disk into memory. @@ -29,8 +29,8 @@ struct program_desc /// \arg desc The program descriptor identifying the file buffer load_file( - fs::file &disk, - const program_desc &desc); + fs::file &disk, + const program_desc &desc); /// Parse and load an ELF file in memory into a loaded image. /// \arg disk The opened UEFI filesystem to load from @@ -38,17 +38,17 @@ load_file( /// \arg add_module Also create a module for this loaded program kernel::init::program * load_program( - fs::file &disk, - const program_desc &desc, - bool add_module = false); + fs::file &disk, + const program_desc &desc, + bool add_module = false); /// Load a file from disk into memory, creating an init args module /// \arg disk The opened UEFI filesystem to load from /// \arg desc The program descriptor identifying the file void load_module( - fs::file &disk, - const program_desc &desc); + fs::file &disk, + const program_desc &desc); /// Verify that a loaded ELF has the j6 kernel header /// \arg program The program to check for a header diff --git a/src/boot/main.cpp b/src/boot/main.cpp index b9b25e2..92ac848 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -36,7 +36,7 @@ const loader::program_desc fb_driver = {L"UEFI framebuffer driver", L"drv.uefi_f const loader::program_desc panic_handler = {L"Serial panic handler", L"panic.serial.elf"}; const loader::program_desc extra_programs[] = { - {L"test application", L"testapp.elf"}, + {L"test application", L"testapp.elf"}, }; /// Change a pointer to point to the higher-half linear-offset version @@ -44,7 +44,7 @@ const loader::program_desc extra_programs[] = { template void change_pointer(T *&pointer) { - pointer = offset_ptr(pointer, kernel::memory::page_offset); + pointer = offset_ptr(pointer, kernel::memory::page_offset); } /// The main procedure for the portion of the loader that runs while @@ -53,50 +53,50 @@ void change_pointer(T *&pointer) init::args * uefi_preboot(uefi::handle image, uefi::system_table *st) { - uefi::boot_services *bs = st->boot_services; - uefi::runtime_services *rs = st->runtime_services; + uefi::boot_services *bs = st->boot_services; + uefi::runtime_services *rs = st->runtime_services; - status_line status {L"Performing UEFI pre-boot"}; + status_line status {L"Performing UEFI pre-boot"}; - hw::check_cpu_supported(); - memory::init_pointer_fixup(bs, rs); + hw::check_cpu_supported(); + memory::init_pointer_fixup(bs, rs); - init::args *args = new init::args; - g_alloc.zero(args, sizeof(init::args)); + init::args *args = new init::args; + g_alloc.zero(args, sizeof(init::args)); - args->magic = init::args_magic; - args->version = init::args_version; - args->runtime_services = rs; - args->acpi_table = hw::find_acpi_table(st); - memory::mark_pointer_fixup(&args->runtime_services); + args->magic = init::args_magic; + args->version = init::args_version; + args->runtime_services = rs; + args->acpi_table = hw::find_acpi_table(st); + memory::mark_pointer_fixup(&args->runtime_services); - paging::allocate_tables(args); + paging::allocate_tables(args); - return args; + return args; } /// Load the kernel and other programs from disk void load_resources(init::args *args, video::screen *screen, uefi::handle image, uefi::boot_services *bs) { - status_line status {L"Loading programs"}; + status_line status {L"Loading programs"}; - fs::file disk = fs::get_boot_volume(image, bs); + fs::file disk = fs::get_boot_volume(image, bs); - if (screen) { - video::make_module(screen); - loader::load_module(disk, fb_driver); - } + if (screen) { + video::make_module(screen); + loader::load_module(disk, fb_driver); + } buffer symbol_table = loader::load_file(disk, {L"symbol table", L"symbol_table.dat"}); - args->symbol_table = reinterpret_cast(symbol_table.pointer); + args->symbol_table = reinterpret_cast(symbol_table.pointer); - args->kernel = loader::load_program(disk, kern_desc, true); - args->init = loader::load_program(disk, init_desc); + args->kernel = loader::load_program(disk, kern_desc, true); + args->init = loader::load_program(disk, init_desc); args->panic = loader::load_program(disk, panic_handler); - for (auto &desc : extra_programs) - loader::load_module(disk, desc); + for (auto &desc : extra_programs) + loader::load_module(disk, desc); loader::verify_kernel_header(*args->kernel); } @@ -104,20 +104,20 @@ load_resources(init::args *args, video::screen *screen, uefi::handle image, uefi memory::efi_mem_map uefi_exit(init::args *args, uefi::handle image, uefi::boot_services *bs) { - status_line status {L"Exiting UEFI", nullptr, false}; + status_line status {L"Exiting UEFI", nullptr, false}; - memory::efi_mem_map map; - map.update(*bs); + memory::efi_mem_map map; + map.update(*bs); - args->mem_map = memory::build_kernel_map(map); - args->frame_blocks = memory::build_frame_blocks(args->mem_map); + args->mem_map = memory::build_kernel_map(map); + args->frame_blocks = memory::build_frame_blocks(args->mem_map); - map.update(*bs); - try_or_raise( - bs->exit_boot_services(image, map.key), - L"Failed to exit boot services"); + map.update(*bs); + try_or_raise( + bs->exit_boot_services(image, map.key), + L"Failed to exit boot services"); - return map; + return map; } } // namespace boot @@ -126,53 +126,53 @@ uefi_exit(init::args *args, uefi::handle image, uefi::boot_services *bs) extern "C" uefi::status efi_main(uefi::handle image, uefi::system_table *st) { - using namespace boot; + using namespace boot; - uefi::boot_services *bs = st->boot_services; - console con(st->con_out); + uefi::boot_services *bs = st->boot_services; + console con(st->con_out); - init::allocation_register *allocs = nullptr; - init::modules_page *modules = nullptr; - memory::allocator::init(allocs, modules, bs); + init::allocation_register *allocs = nullptr; + init::modules_page *modules = nullptr; + memory::allocator::init(allocs, modules, bs); - video::screen *screen = video::pick_mode(bs); - con.announce(); + video::screen *screen = video::pick_mode(bs); + con.announce(); - init::args *args = uefi_preboot(image, st); - load_resources(args, screen, image, bs); - memory::efi_mem_map map = uefi_exit(args, image, st->boot_services); + init::args *args = uefi_preboot(image, st); + load_resources(args, screen, image, bs); + memory::efi_mem_map map = uefi_exit(args, image, st->boot_services); - args->allocations = allocs; - args->modules = reinterpret_cast(modules); + args->allocations = allocs; + args->modules = reinterpret_cast(modules); - status_bar status {screen}; // Switch to fb status display + status_bar status {screen}; // Switch to fb status display - // Map the kernel and panic handler to the appropriate addresses + // Map the kernel and panic handler to the appropriate addresses paging::map_program(args, *args->kernel); paging::map_program(args, *args->panic); - memory::fix_frame_blocks(args); + memory::fix_frame_blocks(args); - init::entrypoint kentry = - reinterpret_cast(args->kernel->entrypoint); - //status.next(); + init::entrypoint kentry = + reinterpret_cast(args->kernel->entrypoint); + //status.next(); - hw::setup_control_regs(); - memory::virtualize(args->pml4, map, st->runtime_services); - //status.next(); + hw::setup_control_regs(); + memory::virtualize(args->pml4, map, st->runtime_services); + //status.next(); - change_pointer(args); - change_pointer(args->pml4); + change_pointer(args); + change_pointer(args->pml4); - change_pointer(args->kernel); - change_pointer(args->kernel->sections.pointer); - change_pointer(args->init); - change_pointer(args->init->sections.pointer); + change_pointer(args->kernel); + change_pointer(args->kernel->sections.pointer); + change_pointer(args->init); + change_pointer(args->init->sections.pointer); - //status.next(); + //status.next(); - kentry(args); - debug_break(); - return uefi::status::unsupported; + kentry(args); + debug_break(); + return uefi::status::unsupported; } diff --git a/src/boot/memory.cpp b/src/boot/memory.cpp index 0cba87f..03a28cd 100644 --- a/src/boot/memory.cpp +++ b/src/boot/memory.cpp @@ -22,56 +22,56 @@ void **fixup_pointers[64]; void update_marked_addresses(uefi::event, void *context) { - uefi::runtime_services *rs = - reinterpret_cast(context); + uefi::runtime_services *rs = + reinterpret_cast(context); - for (size_t i = 0; i < fixup_pointer_index; ++i) { - if (fixup_pointers[i]) - rs->convert_pointer(0, fixup_pointers[i]); - } + for (size_t i = 0; i < fixup_pointer_index; ++i) { + if (fixup_pointers[i]) + rs->convert_pointer(0, fixup_pointers[i]); + } } void init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs) { - status_line status(L"Initializing pointer virtualization event"); + status_line status(L"Initializing pointer virtualization event"); - uefi::event event; - bs->set_mem(&fixup_pointers, sizeof(fixup_pointers), 0); - fixup_pointer_index = 0; + uefi::event event; + bs->set_mem(&fixup_pointers, sizeof(fixup_pointers), 0); + fixup_pointer_index = 0; - try_or_raise( - bs->create_event( - uefi::evt::signal_virtual_address_change, - uefi::tpl::callback, - (uefi::event_notify)&update_marked_addresses, - rs, - &event), - L"Error creating memory virtualization event"); + try_or_raise( + bs->create_event( + uefi::evt::signal_virtual_address_change, + uefi::tpl::callback, + (uefi::event_notify)&update_marked_addresses, + rs, + &event), + L"Error creating memory virtualization event"); } void mark_pointer_fixup(void **p) { - fixup_pointers[fixup_pointer_index++] = p; + fixup_pointers[fixup_pointer_index++] = p; } void virtualize(void *pml4, efi_mem_map &map, uefi::runtime_services *rs) { - paging::add_current_mappings(reinterpret_cast(pml4)); + paging::add_current_mappings(reinterpret_cast(pml4)); - for (auto &desc : map) - desc.virtual_start = desc.physical_start + ::memory::page_offset; + for (auto &desc : map) + desc.virtual_start = desc.physical_start + ::memory::page_offset; - // Write our new PML4 pointer to CR3 - asm volatile ( "mov %0, %%cr3" :: "r" (pml4) ); - __sync_synchronize(); + // Write our new PML4 pointer to CR3 + asm volatile ( "mov %0, %%cr3" :: "r" (pml4) ); + __sync_synchronize(); - try_or_raise( - rs->set_virtual_address_map( - map.length, map.size, map.version, map.entries), - L"Error setting virtual address map"); + try_or_raise( + rs->set_virtual_address_map( + map.length, map.size, map.version, map.entries), + L"Error setting virtual address map"); } diff --git a/src/boot/memory.h b/src/boot/memory.h index 8c570d5..42c649e 100644 --- a/src/boot/memory.h +++ b/src/boot/memory.h @@ -5,8 +5,8 @@ #include namespace uefi { - struct boot_services; - struct runtime_services; + struct boot_services; + struct runtime_services; } namespace boot { @@ -19,7 +19,7 @@ constexpr size_t page_size = 0x1000; /// Get the number of pages needed to hold `bytes` bytes inline constexpr size_t bytes_to_pages(size_t bytes) { - return ((bytes - 1) / page_size) + 1; + return ((bytes - 1) / page_size) + 1; } /// \defgroup pointer_fixup @@ -42,9 +42,9 @@ void mark_pointer_fixup(void **p); /// \arg pml4 The root page table for the new mappings /// \arg map The UEFI memory map, used to update runtime services void virtualize( - void *pml4, - efi_mem_map &map, - uefi::runtime_services *rs); + void *pml4, + efi_mem_map &map, + uefi::runtime_services *rs); } // namespace boot } // namespace memory diff --git a/src/boot/memory_map.cpp b/src/boot/memory_map.cpp index b3caa6d..0e3e31a 100644 --- a/src/boot/memory_map.cpp +++ b/src/boot/memory_map.cpp @@ -21,180 +21,180 @@ using kernel::init::mem_type; void efi_mem_map::update(uefi::boot_services &bs) { - size_t l = total; - uefi::status status = bs.get_memory_map( - &l, entries, &key, &size, &version); - length = l; + size_t l = total; + uefi::status status = bs.get_memory_map( + &l, entries, &key, &size, &version); + length = l; - if (status == uefi::status::success) - return; + if (status == uefi::status::success) + return; - if (status != uefi::status::buffer_too_small) - error::raise(status, L"Error getting memory map size"); + if (status != uefi::status::buffer_too_small) + error::raise(status, L"Error getting memory map size"); - if (entries) { - try_or_raise( - bs.free_pool(reinterpret_cast(entries)), - L"Freeing previous memory map space"); - } + if (entries) { + try_or_raise( + bs.free_pool(reinterpret_cast(entries)), + L"Freeing previous memory map space"); + } - total = length + 10 * size; + total = length + 10 * size; - try_or_raise( - bs.allocate_pool( - uefi::memory_type::loader_data, total, - reinterpret_cast(&entries)), - L"Allocating space for memory map"); + try_or_raise( + bs.allocate_pool( + uefi::memory_type::loader_data, total, + reinterpret_cast(&entries)), + L"Allocating space for memory map"); - length = total; - try_or_raise( - bs.get_memory_map(&length, entries, &key, &size, &version), - L"Getting UEFI memory map"); + length = total; + try_or_raise( + bs.get_memory_map(&length, entries, &key, &size, &version), + L"Getting UEFI memory map"); } static const wchar_t *memory_type_names[] = { - L"reserved memory type", - L"loader code", - L"loader data", - L"boot services code", - L"boot services data", - L"runtime services code", - L"runtime services data", - L"conventional memory", - L"unusable memory", - L"acpi reclaim memory", - L"acpi memory nvs", - L"memory mapped io", - L"memory mapped io port space", - L"pal code", - L"persistent memory" + L"reserved memory type", + L"loader code", + L"loader data", + L"boot services code", + L"boot services data", + L"runtime services code", + L"runtime services data", + L"conventional memory", + L"unusable memory", + L"acpi reclaim memory", + L"acpi memory nvs", + L"memory mapped io", + L"memory mapped io port space", + L"pal code", + L"persistent memory" }; static const wchar_t *kernel_memory_type_names[] = { - L"free", - L"pending", - L"acpi", - L"uefi_runtime", - L"mmio", - L"persistent" + L"free", + L"pending", + L"acpi", + L"uefi_runtime", + L"mmio", + L"persistent" }; static const wchar_t * memory_type_name(uefi::memory_type t) { - if (t < uefi::memory_type::max_memory_type) - return memory_type_names[static_cast(t)]; + if (t < uefi::memory_type::max_memory_type) + return memory_type_names[static_cast(t)]; - return L"Bad Type Value"; + return L"Bad Type Value"; } static const wchar_t * kernel_memory_type_name(kernel::init::mem_type t) { - return kernel_memory_type_names[static_cast(t)]; + return kernel_memory_type_names[static_cast(t)]; } inline bool can_merge(mem_entry &prev, mem_type type, uefi::memory_descriptor &next) { - return - prev.type == type && - prev.start + (page_size * prev.pages) == next.physical_start && - prev.attr == (next.attribute & 0xffffffff); + return + prev.type == type && + prev.start + (page_size * prev.pages) == next.physical_start && + prev.attr == (next.attribute & 0xffffffff); } counted build_kernel_map(efi_mem_map &map) { - status_line status {L"Creating kernel memory map"}; + status_line status {L"Creating kernel memory map"}; - size_t map_size = map.num_entries() * sizeof(mem_entry); - size_t num_pages = bytes_to_pages(map_size); - mem_entry *kernel_map = reinterpret_cast( - g_alloc.allocate_pages(num_pages, alloc_type::mem_map, true)); + size_t map_size = map.num_entries() * sizeof(mem_entry); + size_t num_pages = bytes_to_pages(map_size); + mem_entry *kernel_map = reinterpret_cast( + g_alloc.allocate_pages(num_pages, alloc_type::mem_map, true)); - size_t nent = 0; - bool first = true; - for (auto &desc : map) { - /* - // EFI map dump - console::print(L" eRange %lx (%lx) %x(%s) [%lu]\r\n", - desc.physical_start, desc.attribute, desc.type, memory_type_name(desc.type), desc.number_of_pages); - */ + size_t nent = 0; + bool first = true; + for (auto &desc : map) { + /* + // EFI map dump + console::print(L" eRange %lx (%lx) %x(%s) [%lu]\r\n", + desc.physical_start, desc.attribute, desc.type, memory_type_name(desc.type), desc.number_of_pages); + */ - mem_type type; - switch (desc.type) { - case uefi::memory_type::reserved: - case uefi::memory_type::unusable_memory: - case uefi::memory_type::acpi_memory_nvs: - case uefi::memory_type::pal_code: - continue; + mem_type type; + switch (desc.type) { + case uefi::memory_type::reserved: + case uefi::memory_type::unusable_memory: + case uefi::memory_type::acpi_memory_nvs: + case uefi::memory_type::pal_code: + continue; - case uefi::memory_type::loader_code: - case uefi::memory_type::boot_services_code: - case uefi::memory_type::boot_services_data: - case uefi::memory_type::conventional_memory: - case uefi::memory_type::loader_data: - type = mem_type::free; - break; + case uefi::memory_type::loader_code: + case uefi::memory_type::boot_services_code: + case uefi::memory_type::boot_services_data: + case uefi::memory_type::conventional_memory: + case uefi::memory_type::loader_data: + type = mem_type::free; + break; - case uefi::memory_type::runtime_services_code: - case uefi::memory_type::runtime_services_data: - type = mem_type::uefi_runtime; - break; + case uefi::memory_type::runtime_services_code: + case uefi::memory_type::runtime_services_data: + type = mem_type::uefi_runtime; + break; - case uefi::memory_type::acpi_reclaim_memory: - type = mem_type::acpi; - break; + case uefi::memory_type::acpi_reclaim_memory: + type = mem_type::acpi; + break; - case uefi::memory_type::memory_mapped_io: - case uefi::memory_type::memory_mapped_io_port_space: - type = mem_type::mmio; - break; + case uefi::memory_type::memory_mapped_io: + case uefi::memory_type::memory_mapped_io_port_space: + type = mem_type::mmio; + break; - case uefi::memory_type::persistent_memory: - type = mem_type::persistent; - break; + case uefi::memory_type::persistent_memory: + type = mem_type::persistent; + break; - default: - error::raise( - uefi::status::invalid_parameter, - L"Got an unexpected memory type from UEFI memory map"); - } + default: + error::raise( + uefi::status::invalid_parameter, + L"Got an unexpected memory type from UEFI memory map"); + } - // TODO: validate uefi's map is sorted - if (first) { - first = false; - mem_entry &ent = kernel_map[nent++]; - ent.start = desc.physical_start; - ent.pages = desc.number_of_pages; - ent.type = type; - ent.attr = (desc.attribute & 0xffffffff); - continue; - } + // TODO: validate uefi's map is sorted + if (first) { + first = false; + mem_entry &ent = kernel_map[nent++]; + ent.start = desc.physical_start; + ent.pages = desc.number_of_pages; + ent.type = type; + ent.attr = (desc.attribute & 0xffffffff); + continue; + } - mem_entry &prev = kernel_map[nent - 1]; - if (can_merge(prev, type, desc)) { - prev.pages += desc.number_of_pages; - } else { - mem_entry &next = kernel_map[nent++]; - next.start = desc.physical_start; - next.pages = desc.number_of_pages; - next.type = type; - next.attr = (desc.attribute & 0xffffffff); - } - } + mem_entry &prev = kernel_map[nent - 1]; + if (can_merge(prev, type, desc)) { + prev.pages += desc.number_of_pages; + } else { + mem_entry &next = kernel_map[nent++]; + next.start = desc.physical_start; + next.pages = desc.number_of_pages; + next.type = type; + next.attr = (desc.attribute & 0xffffffff); + } + } - /* - // kernel map dump - for (unsigned i = 0; i < nent; ++i) { - const mem_entry &e = kernel_map[i]; - console::print(L" kRange %lx (%lx) %x(%s) [%lu]\r\n", - e.start, e.attr, e.type, kernel_memory_type_name(e.type), e.pages); - } - */ + /* + // kernel map dump + for (unsigned i = 0; i < nent; ++i) { + const mem_entry &e = kernel_map[i]; + console::print(L" kRange %lx (%lx) %x(%s) [%lu]\r\n", + e.start, e.attr, e.type, kernel_memory_type_name(e.type), e.pages); + } + */ - return { .pointer = kernel_map, .count = nent }; + return { .pointer = kernel_map, .count = nent }; } inline size_t bitmap_size(size_t frames) { return (frames + 63) / 64; } @@ -203,99 +203,99 @@ inline size_t num_blocks(size_t frames) { return (frames + (frames_per_block-1)) counted build_frame_blocks(const counted &kmap) { - status_line status {L"Creating kernel frame accounting map"}; + status_line status {L"Creating kernel frame accounting map"}; - size_t block_count = 0; - size_t total_bitmap_size = 0; - for (size_t i = 0; i < kmap.count; ++i) { - const mem_entry &ent = kmap[i]; - if (ent.type != mem_type::free) - continue; + size_t block_count = 0; + size_t total_bitmap_size = 0; + for (size_t i = 0; i < kmap.count; ++i) { + const mem_entry &ent = kmap[i]; + if (ent.type != mem_type::free) + continue; - block_count += num_blocks(ent.pages); - total_bitmap_size += bitmap_size(ent.pages) * sizeof(uint64_t); - } + block_count += num_blocks(ent.pages); + total_bitmap_size += bitmap_size(ent.pages) * sizeof(uint64_t); + } - size_t total_size = block_count * sizeof(frame_block) + total_bitmap_size; + size_t total_size = block_count * sizeof(frame_block) + total_bitmap_size; - frame_block *blocks = reinterpret_cast( - g_alloc.allocate_pages(bytes_to_pages(total_size), alloc_type::frame_map, true)); + frame_block *blocks = reinterpret_cast( + g_alloc.allocate_pages(bytes_to_pages(total_size), alloc_type::frame_map, true)); - frame_block *next_block = blocks; - for (size_t i = 0; i < kmap.count; ++i) { - const mem_entry &ent = kmap[i]; - if (ent.type != mem_type::free) - continue; + frame_block *next_block = blocks; + for (size_t i = 0; i < kmap.count; ++i) { + const mem_entry &ent = kmap[i]; + if (ent.type != mem_type::free) + continue; - size_t page_count = ent.pages; - uintptr_t base_addr = ent.start; - while (page_count) { - frame_block *blk = next_block++; + size_t page_count = ent.pages; + uintptr_t base_addr = ent.start; + while (page_count) { + frame_block *blk = next_block++; - blk->flags = static_cast(ent.attr); - blk->base = base_addr; - base_addr += frames_per_block * page_size; + blk->flags = static_cast(ent.attr); + blk->base = base_addr; + base_addr += frames_per_block * page_size; - if (page_count >= frames_per_block) { - page_count -= frames_per_block; - blk->count = frames_per_block; - blk->map1 = ~0ull; - g_alloc.memset(blk->map2, sizeof(blk->map2), 0xff); - } else { - blk->count = page_count; - unsigned i = 0; + if (page_count >= frames_per_block) { + page_count -= frames_per_block; + blk->count = frames_per_block; + blk->map1 = ~0ull; + g_alloc.memset(blk->map2, sizeof(blk->map2), 0xff); + } else { + blk->count = page_count; + unsigned i = 0; - uint64_t b1 = (page_count + 4095) / 4096; - blk->map1 = (1 << b1) - 1; + uint64_t b1 = (page_count + 4095) / 4096; + blk->map1 = (1 << b1) - 1; - uint64_t b2 = (page_count + 63) / 64; - uint64_t b2q = b2 / 64; - uint64_t b2r = b2 % 64; - g_alloc.memset(blk->map2, b2q, 0xff); - blk->map2[b2q] = (1 << b2r) - 1; - break; - } - } - } + uint64_t b2 = (page_count + 63) / 64; + uint64_t b2q = b2 / 64; + uint64_t b2r = b2 % 64; + g_alloc.memset(blk->map2, b2q, 0xff); + blk->map2[b2q] = (1 << b2r) - 1; + break; + } + } + } - uint64_t *bitmap = reinterpret_cast(next_block); - for (unsigned i = 0; i < block_count; ++i) { - frame_block &blk = blocks[i]; - blk.bitmap = bitmap; + uint64_t *bitmap = reinterpret_cast(next_block); + for (unsigned i = 0; i < block_count; ++i) { + frame_block &blk = blocks[i]; + blk.bitmap = bitmap; - size_t b = blk.count / 64; - size_t r = blk.count % 64; - g_alloc.memset(blk.bitmap, b*8, 0xff); - blk.bitmap[b] = (1 << r) - 1; + size_t b = blk.count / 64; + size_t r = blk.count % 64; + g_alloc.memset(blk.bitmap, b*8, 0xff); + blk.bitmap[b] = (1 << r) - 1; - bitmap += bitmap_size(blk.count); - } + bitmap += bitmap_size(blk.count); + } - return { .pointer = blocks, .count = block_count }; + return { .pointer = blocks, .count = block_count }; } void fix_frame_blocks(kernel::init::args *args) { - counted &blocks = args->frame_blocks; + counted &blocks = args->frame_blocks; - size_t size = blocks.count * sizeof(frame_block); - for (unsigned i = 0; i < blocks.count; ++i) - size += bitmap_size(blocks[i].count) * sizeof(uint64_t); + size_t size = blocks.count * sizeof(frame_block); + for (unsigned i = 0; i < blocks.count; ++i) + size += bitmap_size(blocks[i].count) * sizeof(uint64_t); - size_t pages = bytes_to_pages(size); - uintptr_t addr = reinterpret_cast(blocks.pointer); + size_t pages = bytes_to_pages(size); + uintptr_t addr = reinterpret_cast(blocks.pointer); - // Map the frame blocks to the appropriate address - paging::map_pages(args, addr, - ::memory::bitmap_start, pages, true, false); + // Map the frame blocks to the appropriate address + paging::map_pages(args, addr, + ::memory::bitmap_start, pages, true, false); - uintptr_t offset = ::memory::bitmap_start - addr; + uintptr_t offset = ::memory::bitmap_start - addr; - for (unsigned i = 0; i < blocks.count; ++i) { - frame_block &blk = blocks[i]; - blk.bitmap = offset_ptr(blk.bitmap, offset); - } + for (unsigned i = 0; i < blocks.count; ++i) { + frame_block &blk = blocks[i]; + blk.bitmap = offset_ptr(blk.bitmap, offset); + } } diff --git a/src/boot/memory_map.h b/src/boot/memory_map.h index 5032a5c..69acb47 100644 --- a/src/boot/memory_map.h +++ b/src/boot/memory_map.h @@ -6,15 +6,15 @@ #include "pointer_manipulation.h" namespace uefi { - struct boot_services; - struct memory_descriptor; + struct boot_services; + struct memory_descriptor; } namespace kernel { namespace init { - struct args; - struct frame_block; - struct mem_entry; + struct args; + struct frame_block; + struct mem_entry; }} namespace boot { @@ -24,29 +24,29 @@ namespace memory { /// as well as the data on how to read it. struct efi_mem_map { - using desc = uefi::memory_descriptor; - using iterator = offset_iterator; + using desc = uefi::memory_descriptor; + using iterator = offset_iterator; - size_t length; ///< Total length of the map data - size_t total; ///< Total allocated space for map data - size_t size; ///< Size of an entry in the array - size_t key; ///< Key for detecting changes - uint32_t version; ///< Version of the `memory_descriptor` struct - desc *entries; ///< The array of UEFI descriptors + size_t length; ///< Total length of the map data + size_t total; ///< Total allocated space for map data + size_t size; ///< Size of an entry in the array + size_t key; ///< Key for detecting changes + uint32_t version; ///< Version of the `memory_descriptor` struct + desc *entries; ///< The array of UEFI descriptors - efi_mem_map() : length(0), total(0), size(0), key(0), version(0), entries(nullptr) {} + efi_mem_map() : length(0), total(0), size(0), key(0), version(0), entries(nullptr) {} - /// Update the map from UEFI - void update(uefi::boot_services &bs); + /// Update the map from UEFI + void update(uefi::boot_services &bs); - /// Get the count of entries in the array - inline size_t num_entries() const { return length / size; } + /// Get the count of entries in the array + inline size_t num_entries() const { return length / size; } - /// Return an iterator to the beginning of the array - inline iterator begin() { return iterator(entries, size); } + /// Return an iterator to the beginning of the array + inline iterator begin() { return iterator(entries, size); } - /// Return an iterator to the end of the array - inline iterator end() { return offset_ptr(entries, length); } + /// Return an iterator to the end of the array + inline iterator end() { return offset_ptr(entries, length); } }; /// Add the kernel's memory map as a module to the kernel args. diff --git a/src/boot/paging.cpp b/src/boot/paging.cpp index 8e700fa..7c929e9 100644 --- a/src/boot/paging.cpp +++ b/src/boot/paging.cpp @@ -60,13 +60,13 @@ constexpr uint64_t table_flags = 0x003; inline void * pop_pages(counted &pages, size_t count) { - if (count > pages.count) - error::raise(uefi::status::out_of_resources, L"Page table cache empty", 0x7ab1e5); + if (count > pages.count) + error::raise(uefi::status::out_of_resources, L"Page table cache empty", 0x7ab1e5); - void *next = pages.pointer; - pages.pointer = offset_ptr(pages.pointer, count*page_size); - pages.count -= count; - return next; + void *next = pages.pointer; + pages.pointer = offset_ptr(pages.pointer, count*page_size); + pages.count -= count; + return next; } /// Iterator over page table entries. @@ -74,204 +74,204 @@ template class page_entry_iterator { public: - /// Constructor. - /// \arg virt Virtual address this iterator is starting at - /// \arg pml4 Root of the page tables to iterate - /// \arg pages Cache of usable table pages - page_entry_iterator( - uintptr_t virt, - page_table *pml4, - counted &pages) : - m_pages(pages) - { - m_table[0] = pml4; - for (unsigned i = 0; i < D; ++i) { - m_index[i] = static_cast((virt >> (12 + 9*(3-i))) & 0x1ff); - ensure_table(i); - } - } + /// Constructor. + /// \arg virt Virtual address this iterator is starting at + /// \arg pml4 Root of the page tables to iterate + /// \arg pages Cache of usable table pages + page_entry_iterator( + uintptr_t virt, + page_table *pml4, + counted &pages) : + m_pages(pages) + { + m_table[0] = pml4; + for (unsigned i = 0; i < D; ++i) { + m_index[i] = static_cast((virt >> (12 + 9*(3-i))) & 0x1ff); + ensure_table(i); + } + } - uintptr_t vaddress() const { - uintptr_t address = 0; - for (unsigned i = 0; i < D; ++i) - address |= static_cast(m_index[i]) << (12 + 9*(3-i)); - if (address & (1ull<<47)) // canonicalize the address - address |= (0xffffull<<48); - return address; - } + uintptr_t vaddress() const { + uintptr_t address = 0; + for (unsigned i = 0; i < D; ++i) + address |= static_cast(m_index[i]) << (12 + 9*(3-i)); + if (address & (1ull<<47)) // canonicalize the address + address |= (0xffffull<<48); + return address; + } - void increment() - { - for (unsigned i = D - 1; i >= 0; --i) { - if (++m_index[i] <= 511) { - for (unsigned j = i + 1; j < D; ++j) - ensure_table(j); - return; - } + void increment() + { + for (unsigned i = D - 1; i >= 0; --i) { + if (++m_index[i] <= 511) { + for (unsigned j = i + 1; j < D; ++j) + ensure_table(j); + return; + } - m_index[i] = 0; - } - } + m_index[i] = 0; + } + } - uint64_t & operator*() { return entry(D-1); } + uint64_t & operator*() { return entry(D-1); } private: - inline uint64_t & entry(unsigned level) { return m_table[level]->entries[m_index[level]]; } + inline uint64_t & entry(unsigned level) { return m_table[level]->entries[m_index[level]]; } - void ensure_table(unsigned level) - { - // We're only dealing with D levels of paging, and - // there must always be a PML4. - if (level < 1 || level >= D) - return; + void ensure_table(unsigned level) + { + // We're only dealing with D levels of paging, and + // there must always be a PML4. + if (level < 1 || level >= D) + return; - // Entry in the parent that points to the table we want - uint64_t & parent_ent = entry(level - 1); + // Entry in the parent that points to the table we want + uint64_t & parent_ent = entry(level - 1); - if (!(parent_ent & 1)) { - page_table *table = reinterpret_cast(pop_pages(m_pages, 1)); - parent_ent = (reinterpret_cast(table) & ~0xfffull) | table_flags; - m_table[level] = table; - } else { - m_table[level] = reinterpret_cast(parent_ent & ~0xfffull); - } - } + if (!(parent_ent & 1)) { + page_table *table = reinterpret_cast(pop_pages(m_pages, 1)); + parent_ent = (reinterpret_cast(table) & ~0xfffull) | table_flags; + m_table[level] = table; + } else { + m_table[level] = reinterpret_cast(parent_ent & ~0xfffull); + } + } - counted &m_pages; - page_table *m_table[D]; - uint16_t m_index[D]; + counted &m_pages; + page_table *m_table[D]; + uint16_t m_index[D]; }; static void add_offset_mappings(page_table *pml4, counted &pages) { - uintptr_t phys = 0; - uintptr_t virt = ::memory::page_offset; // Start of offset-mapped area - size_t page_count = 64 * 1024; // 64 TiB of 1 GiB pages - constexpr size_t GiB = 0x40000000ull; + uintptr_t phys = 0; + uintptr_t virt = ::memory::page_offset; // Start of offset-mapped area + size_t page_count = 64 * 1024; // 64 TiB of 1 GiB pages + constexpr size_t GiB = 0x40000000ull; - page_entry_iterator<2> iterator{virt, pml4, pages}; + page_entry_iterator<2> iterator{virt, pml4, pages}; - while (true) { - *iterator = phys | huge_page_flags; - if (--page_count == 0) - break; + while (true) { + *iterator = phys | huge_page_flags; + if (--page_count == 0) + break; - iterator.increment(); - phys += GiB; - } + iterator.increment(); + phys += GiB; + } } static void add_kernel_pds(page_table *pml4, counted &pages) { - for (unsigned i = pml4e_kernel; i < table_entries; ++i) - pml4->set(i, pop_pages(pages, 1), table_flags); + for (unsigned i = pml4e_kernel; i < table_entries; ++i) + pml4->set(i, pop_pages(pages, 1), table_flags); } void add_current_mappings(page_table *new_pml4) { - // Get the pointer to the current PML4 - page_table *old_pml4 = 0; - asm volatile ( "mov %%cr3, %0" : "=r" (old_pml4) ); + // Get the pointer to the current PML4 + page_table *old_pml4 = 0; + asm volatile ( "mov %%cr3, %0" : "=r" (old_pml4) ); - // Only copy mappings in the lower half - for (int i = 0; i < ::memory::pml4e_kernel; ++i) { - uint64_t entry = old_pml4->entries[i]; - if (entry & 1) - new_pml4->entries[i] = entry; - } + // Only copy mappings in the lower half + for (int i = 0; i < ::memory::pml4e_kernel; ++i) { + uint64_t entry = old_pml4->entries[i]; + if (entry & 1) + new_pml4->entries[i] = entry; + } } void allocate_tables(kernel::init::args *args) { - status_line status(L"Allocating initial page tables"); + status_line status(L"Allocating initial page tables"); - static constexpr size_t pd_tables = 256; // number of pages for kernelspace PDs - static constexpr size_t extra_tables = 64; // number of extra pages + static constexpr size_t pd_tables = 256; // number of pages for kernelspace PDs + static constexpr size_t extra_tables = 64; // number of extra pages - // number of pages for kernelspace PDs + PML4 - static constexpr size_t kernel_tables = pd_tables + 1; + // number of pages for kernelspace PDs + PML4 + static constexpr size_t kernel_tables = pd_tables + 1; - static constexpr size_t tables_needed = kernel_tables + extra_tables; + static constexpr size_t tables_needed = kernel_tables + extra_tables; - void *addr = g_alloc.allocate_pages(tables_needed, alloc_type::page_table, true); - page_table *pml4 = reinterpret_cast(addr); + void *addr = g_alloc.allocate_pages(tables_needed, alloc_type::page_table, true); + page_table *pml4 = reinterpret_cast(addr); - args->pml4 = pml4; - args->page_tables = { .pointer = pml4 + 1, .count = tables_needed - 1 }; + args->pml4 = pml4; + args->page_tables = { .pointer = pml4 + 1, .count = tables_needed - 1 }; - console::print(L" First page (pml4) at: 0x%lx\r\n", pml4); + console::print(L" First page (pml4) at: 0x%lx\r\n", pml4); - add_kernel_pds(pml4, args->page_tables); - add_offset_mappings(pml4, args->page_tables); + add_kernel_pds(pml4, args->page_tables); + add_offset_mappings(pml4, args->page_tables); - //console::print(L" Set up initial mappings, %d spare tables.\r\n", args->table_count); + //console::print(L" Set up initial mappings, %d spare tables.\r\n", args->table_count); } template constexpr bool has_flag(E set, E flag) { - return - (static_cast(set) & static_cast(flag)) == - static_cast(flag); + return + (static_cast(set) & static_cast(flag)) == + static_cast(flag); } void map_pages( - kernel::init::args *args, - uintptr_t phys, uintptr_t virt, - size_t count, bool write_flag, bool exe_flag) + kernel::init::args *args, + uintptr_t phys, uintptr_t virt, + size_t count, bool write_flag, bool exe_flag) { - if (!count) - return; + if (!count) + return; - paging::page_table *pml4 = - reinterpret_cast(args->pml4); + paging::page_table *pml4 = + reinterpret_cast(args->pml4); - page_entry_iterator<4> iterator{virt, pml4, args->page_tables}; + page_entry_iterator<4> iterator{virt, pml4, args->page_tables}; - uint64_t flags = page_flags; - if (!exe_flag) - flags |= (1ull << 63); // set NX bit - if (write_flag) - flags |= 2; + uint64_t flags = page_flags; + if (!exe_flag) + flags |= (1ull << 63); // set NX bit + if (write_flag) + flags |= 2; - while (true) { - *iterator = phys | flags; - if (--count == 0) - break; + while (true) { + *iterator = phys | flags; + if (--count == 0) + break; - iterator.increment(); - phys += page_size; - } + iterator.increment(); + phys += page_size; + } } void map_section( - kernel::init::args *args, - const kernel::init::program_section §ion) + kernel::init::args *args, + const kernel::init::program_section §ion) { - using kernel::init::section_flags; + using kernel::init::section_flags; - map_pages( - args, - section.phys_addr, - section.virt_addr, - memory::bytes_to_pages(section.size), - has_flag(section.type, section_flags::write), - has_flag(section.type, section_flags::execute)); + map_pages( + args, + section.phys_addr, + section.virt_addr, + memory::bytes_to_pages(section.size), + has_flag(section.type, section_flags::write), + has_flag(section.type, section_flags::execute)); } void map_program( - kernel::init::args *args, + kernel::init::args *args, kernel::init::program &program) { - for (auto §ion : program.sections) - paging::map_section(args, section); + for (auto §ion : program.sections) + paging::map_section(args, section); } } // namespace paging diff --git a/src/boot/paging.h b/src/boot/paging.h index 8be7880..498f623 100644 --- a/src/boot/paging.h +++ b/src/boot/paging.h @@ -11,18 +11,18 @@ namespace paging { /// Struct to allow easy accessing of a memory page being used as a page table. struct page_table { - uint64_t entries[512]; + uint64_t entries[512]; - inline page_table * get(int i, uint16_t *flags = nullptr) const { - uint64_t entry = entries[i]; - if ((entry & 1) == 0) return nullptr; - if (flags) *flags = entry & 0xfff; - return reinterpret_cast(entry & ~0xfffull); - } + inline page_table * get(int i, uint16_t *flags = nullptr) const { + uint64_t entry = entries[i]; + if ((entry & 1) == 0) return nullptr; + if (flags) *flags = entry & 0xfff; + return reinterpret_cast(entry & ~0xfffull); + } - inline void set(int i, void *p, uint16_t flags) { - entries[i] = reinterpret_cast(p) | (flags & 0xfff); - } + inline void set(int i, void *p, uint16_t flags) { + entries[i] = reinterpret_cast(p) | (flags & 0xfff); + } }; /// Allocate memory to be used for initial page tables. Initial offset-mapped @@ -46,16 +46,16 @@ void add_current_mappings(page_table *new_pml4); /// \arg write_flag If true, mark the pages writeable /// \arg exe_flag If true, mark the pages executable void map_pages( - kernel::init::args *args, - uintptr_t phys, uintptr_t virt, - size_t count, bool write_flag, bool exe_flag); + kernel::init::args *args, + uintptr_t phys, uintptr_t virt, + size_t count, bool write_flag, bool exe_flag); /// Map the sections of a program in physical memory to their virtual memory /// addresses in the given page tables. /// \arg args The kernel args struct, used for the page table cache and pml4 /// \arg program The program to load void map_program( - kernel::init::args *args, + kernel::init::args *args, kernel::init::program &program); } // namespace paging diff --git a/src/boot/status.cpp b/src/boot/status.cpp index 11491a0..c7fcf90 100644 --- a/src/boot/status.cpp +++ b/src/boot/status.cpp @@ -17,15 +17,15 @@ static constexpr int level_warn = 1; static constexpr int level_fail = 2; static const wchar_t *level_tags[] = { - L" ok ", - L" warn ", - L"failed" + L" ok ", + L" warn ", + L"failed" }; static const uefi::attribute level_colors[] = { - uefi::attribute::green, - uefi::attribute::brown, - uefi::attribute::light_red + uefi::attribute::green, + uefi::attribute::brown, + uefi::attribute::light_red }; status *status::s_current = nullptr; @@ -33,235 +33,235 @@ unsigned status::s_current_type = 0; unsigned status_bar::s_count = 0; status_line::status_line(const wchar_t *message, const wchar_t *context, bool fails_clean) : - status(fails_clean), - m_level(level_ok), - m_depth(0), - m_outer(nullptr) + status(fails_clean), + m_level(level_ok), + m_depth(0), + m_outer(nullptr) { - if (status::s_current_type == status_line::type) { - m_outer = static_cast(s_current); - m_depth = (m_outer ? 1 + m_outer->m_depth : 0); - } - s_current = this; - s_current_type = status_line::type; + if (status::s_current_type == status_line::type) { + m_outer = static_cast(s_current); + m_depth = (m_outer ? 1 + m_outer->m_depth : 0); + } + s_current = this; + s_current_type = status_line::type; - auto out = console::get().m_out; - m_line = out->mode->cursor_row; + auto out = console::get().m_out; + m_line = out->mode->cursor_row; - int indent = 2 * m_depth; - out->set_cursor_position(indent, m_line); - out->set_attribute(uefi::attribute::light_gray); - out->output_string(message); + int indent = 2 * m_depth; + out->set_cursor_position(indent, m_line); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(message); - if (context) { - out->output_string(L": "); - out->output_string(context); - } + if (context) { + out->output_string(L": "); + out->output_string(context); + } - out->output_string(L"\r\n"); - print_status_tag(); + out->output_string(L"\r\n"); + print_status_tag(); } status_line::~status_line() { - if (s_current != this) - error::raise(uefi::status::unsupported, L"Destroying non-current status_line"); + if (s_current != this) + error::raise(uefi::status::unsupported, L"Destroying non-current status_line"); - if (m_outer && m_level > m_outer->m_level) { - m_outer->m_level = m_level; - m_outer->print_status_tag(); - } - s_current = m_outer; + if (m_outer && m_level > m_outer->m_level) { + m_outer->m_level = m_level; + m_outer->print_status_tag(); + } + s_current = m_outer; } void status_line::print_status_tag() { - auto out = console::get().m_out; - int row = out->mode->cursor_row; - int col = out->mode->cursor_column; + auto out = console::get().m_out; + int row = out->mode->cursor_row; + int col = out->mode->cursor_column; - uefi::attribute color = level_colors[m_level]; - const wchar_t *tag = level_tags[m_level]; + uefi::attribute color = level_colors[m_level]; + const wchar_t *tag = level_tags[m_level]; - out->set_cursor_position(50, m_line); + out->set_cursor_position(50, m_line); - out->set_attribute(uefi::attribute::light_gray); - out->output_string(L"["); - out->set_attribute(color); - out->output_string(tag); - out->set_attribute(uefi::attribute::light_gray); - out->output_string(L"]\r\n"); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"["); + out->set_attribute(color); + out->output_string(tag); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"]\r\n"); - out->set_cursor_position(col, row); + out->set_cursor_position(col, row); } void status_line::do_warn(const wchar_t *message, uefi::status status) { - auto out = console::get().m_out; - int row = out->mode->cursor_row; + auto out = console::get().m_out; + int row = out->mode->cursor_row; - if (m_level < level_warn) { - m_level = level_warn; - print_status_tag(); - } + if (m_level < level_warn) { + m_level = level_warn; + print_status_tag(); + } - int indent = 2 + 2 * m_depth; - out->set_cursor_position(indent, row); - out->set_attribute(uefi::attribute::yellow); - out->output_string(message); + int indent = 2 + 2 * m_depth; + out->set_cursor_position(indent, row); + out->set_attribute(uefi::attribute::yellow); + out->output_string(message); - const wchar_t *error = error::message(status); - if (error) { - out->output_string(L": "); - out->output_string(error); - } + const wchar_t *error = error::message(status); + if (error) { + out->output_string(L": "); + out->output_string(error); + } - out->set_attribute(uefi::attribute::light_gray); - out->output_string(L"\r\n"); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"\r\n"); } void status_line::do_fail(const wchar_t *message, uefi::status status) { - auto out = console::get().m_out; - int row = out->mode->cursor_row; + auto out = console::get().m_out; + int row = out->mode->cursor_row; - if (m_level < level_fail) { - m_level = level_fail; - print_status_tag(); - } + if (m_level < level_fail) { + m_level = level_fail; + print_status_tag(); + } - int indent = 2 + 2 * m_depth; - out->set_cursor_position(indent, row); - out->set_attribute(uefi::attribute::red); - out->output_string(message); + int indent = 2 + 2 * m_depth; + out->set_cursor_position(indent, row); + out->set_attribute(uefi::attribute::red); + out->output_string(message); - const wchar_t *error = error::message(status); - if (error) { - out->output_string(L": "); - out->output_string(error); - } + const wchar_t *error = error::message(status); + if (error) { + out->output_string(L": "); + out->output_string(error); + } - out->set_attribute(uefi::attribute::light_gray); - out->output_string(L"\r\n"); + out->set_attribute(uefi::attribute::light_gray); + out->output_string(L"\r\n"); } status_bar::status_bar(video::screen *screen) : - status(), - m_outer(nullptr) + status(), + m_outer(nullptr) { - m_size = (screen->mode.vertical / num_boxes) - 1; - m_top = screen->mode.vertical - m_size; - m_horiz = screen->mode.horizontal; - m_fb = reinterpret_cast(screen->framebuffer.pointer); - m_type = static_cast(screen->mode.layout); - next(); + m_size = (screen->mode.vertical / num_boxes) - 1; + m_top = screen->mode.vertical - m_size; + m_horiz = screen->mode.horizontal; + m_fb = reinterpret_cast(screen->framebuffer.pointer); + m_type = static_cast(screen->mode.layout); + next(); - if (status::s_current_type == status_bar::type) - m_outer = static_cast(s_current); - s_current = this; - s_current_type = status_bar::type; + if (status::s_current_type == status_bar::type) + m_outer = static_cast(s_current); + s_current = this; + s_current_type = status_bar::type; } status_bar::~status_bar() { - if (s_current != this) - error::raise(uefi::status::unsupported, L"Destroying non-current status_bar"); - draw_box(); - s_current = m_outer; + if (s_current != this) + error::raise(uefi::status::unsupported, L"Destroying non-current status_bar"); + draw_box(); + s_current = m_outer; } void status_bar::do_warn(const wchar_t *message, uefi::status status) { - m_status = status; - if (m_level < level_warn) { - m_level = level_warn; - draw_box(); - } + m_status = status; + if (m_level < level_warn) { + m_level = level_warn; + draw_box(); + } } void status_bar::do_fail(const wchar_t *message, uefi::status status) { - m_status = status; - if (m_level < level_fail) { - m_level = level_fail; - draw_box(); - } + m_status = status; + if (m_level < level_fail) { + m_level = level_fail; + draw_box(); + } } static uint32_t make_color(uint8_t r, uint8_t g, uint8_t b, uint16_t type) { - switch (static_cast(type)) { - case video::layout::bgr8: - return - (static_cast(b) << 0) | - (static_cast(g) << 8) | - (static_cast(r) << 16); + switch (static_cast(type)) { + case video::layout::bgr8: + return + (static_cast(b) << 0) | + (static_cast(g) << 8) | + (static_cast(r) << 16); - case video::layout::rgb8: - return - (static_cast(r) << 0) | - (static_cast(g) << 8) | - (static_cast(b) << 16); - - default: - return 0; - } + case video::layout::rgb8: + return + (static_cast(r) << 0) | + (static_cast(g) << 8) | + (static_cast(b) << 16); + + default: + return 0; + } } void status_bar::draw_box() { - static const uint32_t colors[] = {0x909090, 0xf0f0f0}; - constexpr unsigned ncolors = sizeof(colors) / sizeof(uint32_t); + static const uint32_t colors[] = {0x909090, 0xf0f0f0}; + constexpr unsigned ncolors = sizeof(colors) / sizeof(uint32_t); - if (m_fb == nullptr) - return; + if (m_fb == nullptr) + return; - unsigned x0 = m_current * m_size; - unsigned x1 = x0 + m_size - 3; - unsigned y0 = m_top; - unsigned y1 = m_top + m_size - 3; + unsigned x0 = m_current * m_size; + unsigned x1 = x0 + m_size - 3; + unsigned y0 = m_top; + unsigned y1 = m_top + m_size - 3; - uint32_t color = 0; - switch (m_level) { - case level_ok: - color = colors[m_current % ncolors]; - break; - case level_warn: - color = make_color(0xff, 0xb2, 0x34, m_type); - break; - case level_fail: - color = make_color(0xfb, 0x0a, 0x1e, m_type); - break; - default: - color = 0; - } + uint32_t color = 0; + switch (m_level) { + case level_ok: + color = colors[m_current % ncolors]; + break; + case level_warn: + color = make_color(0xff, 0xb2, 0x34, m_type); + break; + case level_fail: + color = make_color(0xfb, 0x0a, 0x1e, m_type); + break; + default: + color = 0; + } - for (unsigned y = y0; y < y1; ++y) - for (unsigned x = x0; x < x1; ++x) - m_fb[y * m_horiz + x] = color; + for (unsigned y = y0; y < y1; ++y) + for (unsigned x = x0; x < x1; ++x) + m_fb[y * m_horiz + x] = color; - if (m_level > level_ok) { - unsigned nbars = static_cast(m_status) & 0xffff; - constexpr unsigned bar_height = 4; + if (m_level > level_ok) { + unsigned nbars = static_cast(m_status) & 0xffff; + constexpr unsigned bar_height = 4; - for (unsigned i = 1; i <= nbars; ++i) { - y0 = m_top - 2 * i * bar_height; - y1 = y0 + bar_height; + for (unsigned i = 1; i <= nbars; ++i) { + y0 = m_top - 2 * i * bar_height; + y1 = y0 + bar_height; - for (unsigned y = y0; y < y1; ++y) - for (unsigned x = x0; x < x1; ++x) - m_fb[y * m_horiz + x] = color; - } - } + for (unsigned y = y0; y < y1; ++y) + for (unsigned x = x0; x < x1; ++x) + m_fb[y * m_horiz + x] = color; + } + } } } // namespace boot diff --git a/src/boot/status.h b/src/boot/status.h index 82a4e62..1d5e890 100644 --- a/src/boot/status.h +++ b/src/boot/status.h @@ -6,125 +6,125 @@ #include namespace uefi { - struct boot_services; + struct boot_services; } namespace boot { namespace video { - struct screen; + struct screen; } // Abstract base class for status reporters. class status { public: - status(bool fails_clean = true) : m_fails_clean(fails_clean) {} + status(bool fails_clean = true) : m_fails_clean(fails_clean) {} - virtual void do_warn(const wchar_t *message, uefi::status status) = 0; - virtual void do_fail(const wchar_t *message, uefi::status status) = 0; + virtual void do_warn(const wchar_t *message, uefi::status status) = 0; + virtual void do_fail(const wchar_t *message, uefi::status status) = 0; - /// Set the state to warning, and print a message. If the state is already at - /// warning or error, the state is unchanged but the message is still printed. - /// \arg message The warning message to print, if text is supported - /// \arg status If set, the error or warning code that should be represented - /// \returns True if there was a status handler to display the warning - inline static bool warn(const wchar_t *message, uefi::status status = uefi::status::success) { - if (!s_current) return false; - s_current->do_warn(message, status); - return s_current->m_fails_clean; - } + /// Set the state to warning, and print a message. If the state is already at + /// warning or error, the state is unchanged but the message is still printed. + /// \arg message The warning message to print, if text is supported + /// \arg status If set, the error or warning code that should be represented + /// \returns True if there was a status handler to display the warning + inline static bool warn(const wchar_t *message, uefi::status status = uefi::status::success) { + if (!s_current) return false; + s_current->do_warn(message, status); + return s_current->m_fails_clean; + } - /// Set the state to error, and print a message. If the state is already at - /// error, the state is unchanged but the message is still printed. - /// \arg message The error message to print, if text is supported - /// \arg status The error or warning code that should be represented - /// \returns True if there was a status handler to display the failure - inline static bool fail(const wchar_t *message, uefi::status status) { - if (!s_current) return false; - s_current->do_fail(message, status); - return s_current->m_fails_clean; - } + /// Set the state to error, and print a message. If the state is already at + /// error, the state is unchanged but the message is still printed. + /// \arg message The error message to print, if text is supported + /// \arg status The error or warning code that should be represented + /// \returns True if there was a status handler to display the failure + inline static bool fail(const wchar_t *message, uefi::status status) { + if (!s_current) return false; + s_current->do_fail(message, status); + return s_current->m_fails_clean; + } protected: - static status *s_current; - static unsigned s_current_type; + static status *s_current; + static unsigned s_current_type; private: - bool m_fails_clean; + bool m_fails_clean; }; /// Scoped status line reporter. Prints a message and an "OK" if no errors /// or warnings were reported before destruction, otherwise reports the /// error or warning. class status_line : - public status + public status { public: - constexpr static unsigned type = 1; + constexpr static unsigned type = 1; - /// Constructor. - /// \arg message Description of the operation in progress - /// \arg context If non-null, printed after `message` and a colon - /// \arg fails_clean If true, this object can handle printing failure - status_line( - const wchar_t *message, - const wchar_t *context = nullptr, - bool fails_clean = true); - ~status_line(); + /// Constructor. + /// \arg message Description of the operation in progress + /// \arg context If non-null, printed after `message` and a colon + /// \arg fails_clean If true, this object can handle printing failure + status_line( + const wchar_t *message, + const wchar_t *context = nullptr, + bool fails_clean = true); + ~status_line(); - virtual void do_warn(const wchar_t *message, uefi::status status) override; - virtual void do_fail(const wchar_t *message, uefi::status status) override; + virtual void do_warn(const wchar_t *message, uefi::status status) override; + virtual void do_fail(const wchar_t *message, uefi::status status) override; private: - void print_status_tag(); + void print_status_tag(); - size_t m_line; - int m_level; - int m_depth; + size_t m_line; + int m_level; + int m_depth; - status_line *m_outer; + status_line *m_outer; }; /// Scoped status bar reporter. Draws a row of boxes along the bottom of /// the screen, turning one red if there's an error in that step. class status_bar : - public status + public status { public: - constexpr static unsigned type = 2; + constexpr static unsigned type = 2; - /// Constructor. - status_bar(video::screen *screen); - ~status_bar(); + /// Constructor. + status_bar(video::screen *screen); + ~status_bar(); - virtual void do_warn(const wchar_t *message, uefi::status status) override; - virtual void do_fail(const wchar_t *message, uefi::status status) override; + virtual void do_warn(const wchar_t *message, uefi::status status) override; + virtual void do_fail(const wchar_t *message, uefi::status status) override; - inline void next() { - m_current = s_count++; - m_level = 0; - m_status = uefi::status::success; - draw_box(); - } + inline void next() { + m_current = s_count++; + m_level = 0; + m_status = uefi::status::success; + draw_box(); + } private: - void draw_box(); + void draw_box(); - uint32_t *m_fb; - uint32_t m_size; - uint32_t m_top; - uint32_t m_horiz; + uint32_t *m_fb; + uint32_t m_size; + uint32_t m_top; + uint32_t m_horiz; - int m_level; - uefi::status m_status; + int m_level; + uefi::status m_status; - uint16_t m_type; - uint16_t m_current; + uint16_t m_type; + uint16_t m_current; - status_bar *m_outer; + status_bar *m_outer; - static unsigned s_count; + static unsigned s_count; }; } // namespace boot diff --git a/src/boot/support.cpp b/src/boot/support.cpp index d631a75..ec6ec8a 100644 --- a/src/boot/support.cpp +++ b/src/boot/support.cpp @@ -10,11 +10,11 @@ extern "C" { __attribute__ ((__weak__)) void *memcpy(void *dest, const void *src, size_t n) { - uint8_t *cdest = reinterpret_cast(dest); - const uint8_t *csrc = reinterpret_cast(src); - for (size_t i = 0; i < n; ++i) - cdest[i] = csrc[i]; - return dest; + uint8_t *cdest = reinterpret_cast(dest); + const uint8_t *csrc = reinterpret_cast(src); + for (size_t i = 0; i < n; ++i) + cdest[i] = csrc[i]; + return dest; } /// Basic memset() implementation for clang. Clang requires freestanding code @@ -23,15 +23,15 @@ void *memcpy(void *dest, const void *src, size_t n) __attribute__ ((__weak__)) void *memset(void *dest, int c, size_t n) { - uint8_t *cdest = reinterpret_cast(dest); - for (size_t i = 0; i < n; ++i) - cdest[i] = static_cast(c); - return dest; + uint8_t *cdest = reinterpret_cast(dest); + for (size_t i = 0; i < n; ++i) + cdest[i] = static_cast(c); + return dest; } int _purecall() { - ::boot::error::raise(uefi::status::unsupported, L"Pure virtual call"); + ::boot::error::raise(uefi::status::unsupported, L"Pure virtual call"); } /// Clang can emit calls to atexit() in constructors or destructors, but diff --git a/src/boot/video.cpp b/src/boot/video.cpp index a3c1469..8d89137 100644 --- a/src/boot/video.cpp +++ b/src/boot/video.cpp @@ -20,102 +20,102 @@ using kernel::init::module_type; static uefi::protos::graphics_output * get_gop(uefi::boot_services *bs) { - uefi::protos::graphics_output *gop = nullptr; - uefi::guid guid = uefi::protos::graphics_output::guid; + uefi::protos::graphics_output *gop = nullptr; + uefi::guid guid = uefi::protos::graphics_output::guid; - uefi::status has_gop = bs->locate_protocol(&guid, nullptr, - (void **)&gop); + uefi::status has_gop = bs->locate_protocol(&guid, nullptr, + (void **)&gop); - if (has_gop != uefi::status::success) - return nullptr; + if (has_gop != uefi::status::success) + return nullptr; - return gop; + return gop; } screen * pick_mode(uefi::boot_services *bs) { - uefi::protos::graphics_output *gop = get_gop(bs); - if (!gop) { - console::print(L"No framebuffer found.\r\n"); - return nullptr; - } + uefi::protos::graphics_output *gop = get_gop(bs); + if (!gop) { + console::print(L"No framebuffer found.\r\n"); + return nullptr; + } - uefi::graphics_output_mode_info *info = gop->mode->info; + uefi::graphics_output_mode_info *info = gop->mode->info; - uint32_t best = gop->mode->mode; - uint32_t res = info->horizontal_resolution * info->vertical_resolution; - int pixmode = static_cast(info->pixel_format); + uint32_t best = gop->mode->mode; + uint32_t res = info->horizontal_resolution * info->vertical_resolution; + int pixmode = static_cast(info->pixel_format); - const uint32_t modes = gop->mode->max_mode; - for (uint32_t i = 0; i < modes; ++i) { - size_t size = 0; - uefi::graphics_output_mode_info *new_info = nullptr; + const uint32_t modes = gop->mode->max_mode; + for (uint32_t i = 0; i < modes; ++i) { + size_t size = 0; + uefi::graphics_output_mode_info *new_info = nullptr; - try_or_raise( - gop->query_mode(i, &size, &new_info), - L"Failed to find a graphics mode the driver claimed to support"); + try_or_raise( + gop->query_mode(i, &size, &new_info), + L"Failed to find a graphics mode the driver claimed to support"); - const uint32_t new_res = new_info->horizontal_resolution * new_info->vertical_resolution; - int new_pixmode = static_cast(new_info->pixel_format); + const uint32_t new_res = new_info->horizontal_resolution * new_info->vertical_resolution; + int new_pixmode = static_cast(new_info->pixel_format); - if (new_pixmode <= pixmode && new_res >= res) { - best = i; - res = new_res; - pixmode = new_pixmode; - } - } + if (new_pixmode <= pixmode && new_res >= res) { + best = i; + res = new_res; + pixmode = new_pixmode; + } + } - screen *s = new screen; - s->mode = { - .vertical = gop->mode->info->vertical_resolution, - .horizontal = gop->mode->info->horizontal_resolution, - .scanline = gop->mode->info->pixels_per_scanline, - .layout = layout::unknown, - }; + screen *s = new screen; + s->mode = { + .vertical = gop->mode->info->vertical_resolution, + .horizontal = gop->mode->info->horizontal_resolution, + .scanline = gop->mode->info->pixels_per_scanline, + .layout = layout::unknown, + }; - s->framebuffer = { - .pointer = reinterpret_cast(gop->mode->frame_buffer_base), - .count = gop->mode->frame_buffer_size - }; + s->framebuffer = { + .pointer = reinterpret_cast(gop->mode->frame_buffer_base), + .count = gop->mode->frame_buffer_size + }; - wchar_t const * type = nullptr; - switch (info->pixel_format) { - case uefi::pixel_format::rgb8: - type = L"rgb8"; - s->mode.layout = layout::rgb8; - break; + wchar_t const * type = nullptr; + switch (info->pixel_format) { + case uefi::pixel_format::rgb8: + type = L"rgb8"; + s->mode.layout = layout::rgb8; + break; - case uefi::pixel_format::bgr8: - type = L"bgr8"; - s->mode.layout = layout::bgr8; - break; + case uefi::pixel_format::bgr8: + type = L"bgr8"; + s->mode.layout = layout::bgr8; + break; - default: - type = L"unknown"; - } + default: + type = L"unknown"; + } - console::print(L"Found framebuffer: %dx%d[%d] type %s @0x%x\r\n", - info->horizontal_resolution, info->vertical_resolution, - info->pixels_per_scanline, type, gop->mode->frame_buffer_base); + console::print(L"Found framebuffer: %dx%d[%d] type %s @0x%x\r\n", + info->horizontal_resolution, info->vertical_resolution, + info->pixels_per_scanline, type, gop->mode->frame_buffer_base); - try_or_raise( - gop->set_mode(best), - L"Failed to set graphics mode"); + try_or_raise( + gop->set_mode(best), + L"Failed to set graphics mode"); - return s; + return s; } void make_module(screen *s) { - using kernel::init::module_framebuffer; - module_framebuffer *modfb = g_alloc.allocate_module(); - modfb->mod_type = module_type::framebuffer; - modfb->type = fb_type::uefi; + using kernel::init::module_framebuffer; + module_framebuffer *modfb = g_alloc.allocate_module(); + modfb->mod_type = module_type::framebuffer; + modfb->type = fb_type::uefi; - modfb->framebuffer = s->framebuffer; - modfb->mode = s->mode; + modfb->framebuffer = s->framebuffer; + modfb->mode = s->mode; } } // namespace video diff --git a/src/boot/video.h b/src/boot/video.h index 97a7eca..d43ce70 100644 --- a/src/boot/video.h +++ b/src/boot/video.h @@ -8,7 +8,7 @@ #include "init_args.h" namespace uefi { - struct boot_services; + struct boot_services; } namespace boot { @@ -18,8 +18,8 @@ using kernel::init::video_mode; using layout = kernel::init::fb_layout; struct screen { - buffer framebuffer; - video_mode mode; + buffer framebuffer; + video_mode mode; }; /// Pick the best video mode and set up the screen diff --git a/src/include/basic_types.h b/src/include/basic_types.h index 342f574..0a4f05f 100644 --- a/src/include/basic_types.h +++ b/src/include/basic_types.h @@ -34,11 +34,11 @@ template <> struct integral { using type = unsigned long lon template struct integral_constant { - using value_type = T; - using type = integral_constant; - static constexpr value_type value = v; - constexpr operator value_type() const noexcept { return value; } - constexpr value_type operator()() const noexcept { return value; } + using value_type = T; + using type = integral_constant; + static constexpr value_type value = v; + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } }; using true_type = integral_constant; diff --git a/src/include/counted.h b/src/include/counted.h index 066b414..2a5e460 100644 --- a/src/include/counted.h +++ b/src/include/counted.h @@ -10,37 +10,37 @@ template struct counted { - T *pointer; - size_t count; + T *pointer; + size_t count; - /// Index this object as an array of type T - inline T & operator [] (int i) { return pointer[i]; } + /// Index this object as an array of type T + inline T & operator [] (int i) { return pointer[i]; } - /// Index this object as a const array of type T - inline const T & operator [] (int i) const { return pointer[i]; } + /// Index this object as a const array of type T + inline const T & operator [] (int i) const { return pointer[i]; } - using iterator = offset_iterator; - using const_iterator = const_offset_iterator; + using iterator = offset_iterator; + using const_iterator = const_offset_iterator; - /// Return an iterator to the beginning of the array - inline iterator begin() { return iterator(pointer, sizeof(T)); } + /// Return an iterator to the beginning of the array + inline iterator begin() { return iterator(pointer, sizeof(T)); } - /// Return an iterator to the end of the array - inline iterator end() { return offset_ptr(pointer, sizeof(T)*count); } + /// Return an iterator to the end of the array + inline iterator end() { return offset_ptr(pointer, sizeof(T)*count); } - /// Return an iterator to the beginning of the array - inline const_iterator begin() const { return const_iterator(pointer, sizeof(T)); } + /// Return an iterator to the beginning of the array + inline const_iterator begin() const { return const_iterator(pointer, sizeof(T)); } - /// Return an iterator to the end of the array - inline const_iterator end() const { return offset_ptr(pointer, sizeof(T)*count); } + /// Return an iterator to the end of the array + inline const_iterator end() const { return offset_ptr(pointer, sizeof(T)*count); } }; /// Specialize for `void` which cannot be indexed or iterated template <> struct counted { - void *pointer; - size_t count; + void *pointer; + size_t count; }; using buffer = counted; diff --git a/src/include/enum_bitfields.h b/src/include/enum_bitfields.h index 49f9acc..29b9050 100644 --- a/src/include/enum_bitfields.h +++ b/src/include/enum_bitfields.h @@ -9,41 +9,41 @@ constexpr bool is_enum_bitfield(E) { return false; } template struct enum_or_int { - static constexpr bool value = - is_enum_bitfield(E{}) || types::is_integral::value; + static constexpr bool value = + is_enum_bitfield(E{}) || types::is_integral::value; }; template struct both_enum_or_int { - static constexpr bool value = - types::conjunction< enum_or_int, enum_or_int >::value; + static constexpr bool value = + types::conjunction< enum_or_int, enum_or_int >::value; }; template constexpr typename types::enable_if::value,E>::type& operator |= (E &lhs, F rhs) { - return lhs = static_cast( - static_cast::type>(lhs) | - static_cast::type>(rhs)); + return lhs = static_cast( + static_cast::type>(lhs) | + static_cast::type>(rhs)); } template constexpr typename types::enable_if::value,E>::type& operator &= (E &lhs, F rhs) { - return lhs = static_cast( - static_cast::type>(lhs) & - static_cast::type>(rhs)); + return lhs = static_cast( + static_cast::type>(lhs) & + static_cast::type>(rhs)); } template constexpr typename types::enable_if::value,E>::type& operator ^= (E &lhs, F rhs) { - return lhs = static_cast( - static_cast::type>(lhs) ^ - static_cast::type>(rhs)); + return lhs = static_cast( + static_cast::type>(lhs) ^ + static_cast::type>(rhs)); } template @@ -75,15 +75,15 @@ operator && (E rhs, E lhs) { return (rhs & lhs) == lhs; } template constexpr bool has(E set, F flags) { - return - (static_cast::type>(set) & - static_cast::type>(flags)) == - static_cast::type>(flags); + return + (static_cast::type>(set) & + static_cast::type>(flags)) == + static_cast::type>(flags); } } // namespace bitfields #define is_bitfield(name) \ - constexpr bool is_enum_bitfield(name) { return true; } \ - using namespace ::bitfields; + constexpr bool is_enum_bitfield(name) { return true; } \ + using namespace ::bitfields; diff --git a/src/include/init_args.h b/src/include/init_args.h index 46ce0b3..acd10f5 100644 --- a/src/include/init_args.h +++ b/src/include/init_args.h @@ -9,32 +9,32 @@ namespace kernel { namespace init { enum class module_type : uint8_t { - none, - program, - framebuffer, + none, + program, + framebuffer, }; enum class module_flags : uint8_t { - none = 0x00, + none = 0x00, - /// This module was already handled by the bootloader, - /// no action is needed. The module is included for - /// informational purposes only. - no_load = 0x01, + /// This module was already handled by the bootloader, + /// no action is needed. The module is included for + /// informational purposes only. + no_load = 0x01, }; struct module { - module_type mod_type; - module_flags mod_flags; - uint32_t mod_length; + module_type mod_type; + module_flags mod_flags; + uint32_t mod_length; }; struct module_program : - public module + public module { - uintptr_t base_address; - char filename[]; + uintptr_t base_address; + char filename[]; }; enum class fb_layout : uint8_t { rgb8, bgr8, unknown = 0xff }; @@ -42,25 +42,25 @@ enum class fb_type : uint8_t { uefi }; struct video_mode { - uint32_t vertical; - uint32_t horizontal; - uint32_t scanline; - fb_layout layout; + uint32_t vertical; + uint32_t horizontal; + uint32_t scanline; + fb_layout layout; }; struct module_framebuffer : - public module + public module { - buffer framebuffer; - video_mode mode; - fb_type type; + buffer framebuffer; + video_mode mode; + fb_type type; }; struct modules_page { - uint8_t count; - module *modules; - uintptr_t next; + uint8_t count; + module *modules; + uintptr_t next; }; } // namespace init diff --git a/src/include/j6/errors.h b/src/include/j6/errors.h index 2920ec3..e06ff41 100644 --- a/src/include/j6/errors.h +++ b/src/include/j6/errors.h @@ -2,19 +2,19 @@ /// \file errors.h /// Collection of constants for the j6_status_t type -#define j6_status_error 0x8000000000000000 -#define j6_err(x) ((x) | j6_status_error) -#define j6_is_err(x) (((x) & j6_status_error) == j6_status_error) +#define j6_status_error 0x8000000000000000 +#define j6_err(x) ((x) | j6_status_error) +#define j6_is_err(x) (((x) & j6_status_error) == j6_status_error) -#define j6_status_ok 0x0000 +#define j6_status_ok 0x0000 -#define j6_status_closed 0x1000 -#define j6_status_destroyed 0x1001 -#define j6_status_exists 0x1002 +#define j6_status_closed 0x1000 +#define j6_status_destroyed 0x1001 +#define j6_status_exists 0x1002 -#define j6_err_nyi j6_err(0x0001) -#define j6_err_unexpected j6_err(0x0002) -#define j6_err_invalid_arg j6_err(0x0003) -#define j6_err_not_ready j6_err(0x0004) -#define j6_err_insufficient j6_err(0x0005) +#define j6_err_nyi j6_err(0x0001) +#define j6_err_unexpected j6_err(0x0002) +#define j6_err_invalid_arg j6_err(0x0003) +#define j6_err_not_ready j6_err(0x0004) +#define j6_err_insufficient j6_err(0x0005) diff --git a/src/include/j6/flags.h b/src/include/j6/flags.h index 6cc89dd..3d1bb93 100644 --- a/src/include/j6/flags.h +++ b/src/include/j6/flags.h @@ -6,5 +6,5 @@ enum j6_vm_flags { #define VM_FLAG(name, v) j6_vm_flag_ ## name = v, #include "j6/tables/vm_flags.inc" #undef VM_FLAG - j6_vm_flags_MAX + j6_vm_flags_MAX }; diff --git a/src/include/j6/init.h b/src/include/j6/init.h index 1729bd3..a8afe20 100644 --- a/src/include/j6/init.h +++ b/src/include/j6/init.h @@ -5,33 +5,33 @@ #include #include "j6/types.h" -enum j6_init_type { // `value` is a: - j6_init_handle_self, // Handle to the system - j6_init_handle_other, // Handle to this process - j6_init_desc_framebuffer // Pointer to a j6_init_framebuffer descriptor +enum j6_init_type { // `value` is a: + j6_init_handle_self, // Handle to the system + j6_init_handle_other, // Handle to this process + j6_init_desc_framebuffer // Pointer to a j6_init_framebuffer descriptor }; struct j6_typed_handle { - enum j6_object_type type; - j6_handle_t handle; + enum j6_object_type type; + j6_handle_t handle; }; struct j6_init_value { - enum j6_init_type type; - union { - struct j6_typed_handle handle; - void *data; - }; + enum j6_init_type type; + union { + struct j6_typed_handle handle; + void *data; + }; }; /// Structure defining a framebuffer. /// `flags` has the following bits: /// 0-3: Pixel layout. 0000: rgb8, 0001: bgr8 struct j6_init_framebuffer { - uintptr_t addr; - size_t size; - uint32_t vertical; - uint32_t horizontal; - uint32_t scanline; - uint32_t flags; + uintptr_t addr; + size_t size; + uint32_t vertical; + uint32_t horizontal; + uint32_t scanline; + uint32_t flags; }; diff --git a/src/include/j6/signals.h b/src/include/j6/signals.h index bb625a7..cb9d417 100644 --- a/src/include/j6/signals.h +++ b/src/include/j6/signals.h @@ -3,8 +3,8 @@ /// Collection of constants for the j6_signal_t type // Signals 0-15 are common to all types -#define j6_signal_no_handles (1ull << 0) -#define j6_signal_closed (1ull << 1) +#define j6_signal_no_handles (1ull << 0) +#define j6_signal_closed (1ull << 1) // Signals 16-47 are defined per-object-type @@ -43,32 +43,32 @@ #define j7_signal_event31 (1ull << 47) // System signals -#define j6_signal_system_has_log (1ull << 16) +#define j6_signal_system_has_log (1ull << 16) // Channel signals -#define j6_signal_channel_can_send (1ull << 16) -#define j6_signal_channel_can_recv (1ull << 17) +#define j6_signal_channel_can_send (1ull << 16) +#define j6_signal_channel_can_recv (1ull << 17) // Endpoint signals -#define j6_signal_endpoint_can_send (1ull << 16) -#define j6_signal_endpoint_can_recv (1ull << 17) +#define j6_signal_endpoint_can_send (1ull << 16) +#define j6_signal_endpoint_can_recv (1ull << 17) // Signals 48-63 are user-defined signals -#define j6_signal_user0 (1ull << 48) -#define j6_signal_user1 (1ull << 49) -#define j6_signal_user2 (1ull << 50) -#define j6_signal_user3 (1ull << 51) -#define j6_signal_user4 (1ull << 52) -#define j6_signal_user5 (1ull << 53) -#define j6_signal_user6 (1ull << 54) -#define j6_signal_user7 (1ull << 55) -#define j6_signal_user8 (1ull << 56) -#define j6_signal_user9 (1ull << 57) -#define j6_signal_user10 (1ull << 58) -#define j6_signal_user11 (1ull << 59) -#define j6_signal_user12 (1ull << 60) -#define j6_signal_user13 (1ull << 61) -#define j6_signal_user14 (1ull << 62) -#define j6_signal_user15 (1ull << 63) +#define j6_signal_user0 (1ull << 48) +#define j6_signal_user1 (1ull << 49) +#define j6_signal_user2 (1ull << 50) +#define j6_signal_user3 (1ull << 51) +#define j6_signal_user4 (1ull << 52) +#define j6_signal_user5 (1ull << 53) +#define j6_signal_user6 (1ull << 54) +#define j6_signal_user7 (1ull << 55) +#define j6_signal_user8 (1ull << 56) +#define j6_signal_user9 (1ull << 57) +#define j6_signal_user10 (1ull << 58) +#define j6_signal_user11 (1ull << 59) +#define j6_signal_user12 (1ull << 60) +#define j6_signal_user13 (1ull << 61) +#define j6_signal_user14 (1ull << 62) +#define j6_signal_user15 (1ull << 63) -#define j6_signal_user_mask (0xffffull << 48) +#define j6_signal_user_mask (0xffffull << 48) diff --git a/src/include/j6/types.h b/src/include/j6/types.h index 26e03f1..2eeffe3 100644 --- a/src/include/j6/types.h +++ b/src/include/j6/types.h @@ -41,5 +41,5 @@ enum j6_object_type { #include "j6/tables/object_types.inc" #undef OBJECT_TYPE - j6_object_type_max + j6_object_type_max }; diff --git a/src/include/kernel_args.h b/src/include/kernel_args.h index 73ba20d..1b30b43 100644 --- a/src/include/kernel_args.h +++ b/src/include/kernel_args.h @@ -16,83 +16,83 @@ constexpr uint16_t header_version = 2; constexpr uint16_t min_header_version = 2; enum class section_flags : uint32_t { - none = 0, - execute = 1, - write = 2, - read = 4, + none = 0, + execute = 1, + write = 2, + read = 4, }; struct program_section { - uintptr_t phys_addr; - uintptr_t virt_addr; - uint32_t size; - section_flags type; + uintptr_t phys_addr; + uintptr_t virt_addr; + uint32_t size; + section_flags type; }; struct program { - uintptr_t entrypoint; - uintptr_t phys_base; - counted sections; + uintptr_t entrypoint; + uintptr_t phys_base; + counted sections; }; enum class mem_type : uint32_t { - free, - pending, - acpi, - uefi_runtime, - mmio, - persistent + free, + pending, + acpi, + uefi_runtime, + mmio, + persistent }; /// Structure to hold an entry in the memory map. struct mem_entry { - uintptr_t start; - size_t pages; - mem_type type; - uint32_t attr; + uintptr_t start; + size_t pages; + mem_type type; + uint32_t attr; }; enum class allocation_type : uint8_t { - none, page_table, mem_map, frame_map, file, program, init_args, + none, page_table, mem_map, frame_map, file, program, init_args, }; /// A single contiguous allocation of pages struct page_allocation { - uintptr_t address; - uint32_t count; - allocation_type type; + uintptr_t address; + uint32_t count; + allocation_type type; }; /// A page-sized register of page_allocation entries struct allocation_register { - allocation_register *next; - uint8_t count; + allocation_register *next; + uint8_t count; - uint8_t reserved0; - uint16_t reserved1; - uint32_t reserved2; + uint8_t reserved0; + uint16_t reserved1; + uint32_t reserved2; - page_allocation entries[255]; + page_allocation entries[255]; }; enum class frame_flags : uint32_t { - uncacheable = 0x00000001, - write_combining = 0x00000002, - write_through = 0x00000004, - write_back = 0x00000008, - uncache_exported = 0x00000010, + uncacheable = 0x00000001, + write_combining = 0x00000002, + write_through = 0x00000004, + write_back = 0x00000008, + uncache_exported = 0x00000010, - write_protect = 0x00001000, - read_protect = 0x00002000, - exec_protect = 0x00004000, - non_volatile = 0x00008000, + write_protect = 0x00001000, + read_protect = 0x00002000, + exec_protect = 0x00004000, + non_volatile = 0x00008000, - read_only = 0x00020000, - earmarked = 0x00040000, - hw_crypto = 0x00080000, + read_only = 0x00020000, + earmarked = 0x00040000, + hw_crypto = 0x00080000, }; @@ -100,39 +100,39 @@ constexpr size_t frames_per_block = 64 * 64 * 64; struct frame_block { - uintptr_t base; - uint32_t count; - frame_flags flags; - uint64_t map1; - uint64_t map2[64]; - uint64_t *bitmap; + uintptr_t base; + uint32_t count; + frame_flags flags; + uint64_t map1; + uint64_t map2[64]; + uint64_t *bitmap; }; enum class boot_flags : uint16_t { - none = 0x0000, - debug = 0x0001 + none = 0x0000, + debug = 0x0001 }; struct args { - uint32_t magic; - uint16_t version; - boot_flags flags; + uint32_t magic; + uint16_t version; + boot_flags flags; - void *pml4; - counted page_tables; - counted mem_map; - counted frame_blocks; + void *pml4; + counted page_tables; + counted mem_map; + counted frame_blocks; - program *kernel; - program *init; - program *panic; - allocation_register *allocations; - uintptr_t modules; - uintptr_t symbol_table; + program *kernel; + program *init; + program *panic; + allocation_register *allocations; + uintptr_t modules; + uintptr_t symbol_table; - void *runtime_services; - void *acpi_table; + void *runtime_services; + void *acpi_table; } __attribute__((aligned(alignof(max_align_t)))); diff --git a/src/include/kernel_memory.h b/src/include/kernel_memory.h index 248eed2..2899a3b 100644 --- a/src/include/kernel_memory.h +++ b/src/include/kernel_memory.h @@ -7,79 +7,79 @@ namespace memory { - /// Size of a single page frame. - constexpr size_t frame_size = 0x1000; + /// Size of a single page frame. + constexpr size_t frame_size = 0x1000; - /// Start of kernel memory. - constexpr uintptr_t kernel_offset = 0xffff800000000000ull; + /// Start of kernel memory. + constexpr uintptr_t kernel_offset = 0xffff800000000000ull; - /// Offset from physical where page tables are mapped. - constexpr uintptr_t page_offset = 0xffffc00000000000ull; + /// Offset from physical where page tables are mapped. + constexpr uintptr_t page_offset = 0xffffc00000000000ull; - /// Max number of pages for a kernel stack - constexpr unsigned kernel_stack_pages = 2; + /// Max number of pages for a kernel stack + constexpr unsigned kernel_stack_pages = 2; - /// Max number of pages for a kernel buffer - constexpr unsigned kernel_buffer_pages = 16; + /// Max number of pages for a kernel buffer + constexpr unsigned kernel_buffer_pages = 16; - /// Max size of the kernel heap - constexpr size_t kernel_max_heap = 0x8000000000ull; // 512GiB + /// Max size of the kernel heap + constexpr size_t kernel_max_heap = 0x8000000000ull; // 512GiB - /// Start of the kernel heap - constexpr uintptr_t heap_start = page_offset - kernel_max_heap; + /// Start of the kernel heap + constexpr uintptr_t heap_start = page_offset - kernel_max_heap; - /// Max size of the kernel stacks area - constexpr size_t kernel_max_stacks = 0x8000000000ull; // 512GiB + /// Max size of the kernel stacks area + constexpr size_t kernel_max_stacks = 0x8000000000ull; // 512GiB - /// Start of the kernel stacks - constexpr uintptr_t stacks_start = heap_start - kernel_max_stacks; + /// Start of the kernel stacks + constexpr uintptr_t stacks_start = heap_start - kernel_max_stacks; - /// Max size of kernel buffers area - constexpr size_t kernel_max_buffers = 0x8000000000ull; // 512GiB + /// Max size of kernel buffers area + constexpr size_t kernel_max_buffers = 0x8000000000ull; // 512GiB - /// Start of kernel buffers - constexpr uintptr_t buffers_start = stacks_start - kernel_max_buffers; + /// Start of kernel buffers + constexpr uintptr_t buffers_start = stacks_start - kernel_max_buffers; - /// Max size of kernel bitmap area - constexpr size_t kernel_max_bitmap = 0x8000000000ull; // 512GiB + /// Max size of kernel bitmap area + constexpr size_t kernel_max_bitmap = 0x8000000000ull; // 512GiB - /// Start of kernel bitmap - constexpr uintptr_t bitmap_start = buffers_start - kernel_max_bitmap; + /// Start of kernel bitmap + constexpr uintptr_t bitmap_start = buffers_start - kernel_max_bitmap; - /// First kernel space PML4 entry - constexpr unsigned pml4e_kernel = 256; + /// First kernel space PML4 entry + constexpr unsigned pml4e_kernel = 256; - /// First offset-mapped space PML4 entry - constexpr unsigned pml4e_offset = 384; + /// First offset-mapped space PML4 entry + constexpr unsigned pml4e_offset = 384; - /// Number of page_table entries - constexpr unsigned table_entries = 512; + /// Number of page_table entries + constexpr unsigned table_entries = 512; - /// Helper to determine if a physical address can be accessed - /// through the page_offset area. - inline bool page_mappable(uintptr_t a) { return (a & page_offset) == 0; } + /// Helper to determine if a physical address can be accessed + /// through the page_offset area. + inline bool page_mappable(uintptr_t a) { return (a & page_offset) == 0; } - /// Convert a physical address to a virtual one (in the offset-mapped area) - template T * to_virtual(uintptr_t a) { - return reinterpret_cast(a|page_offset); - } + /// Convert a physical address to a virtual one (in the offset-mapped area) + template T * to_virtual(uintptr_t a) { + return reinterpret_cast(a|page_offset); + } - /// Convert a physical address to a virtual one (in the offset-mapped area) - template T * to_virtual(T *p) { - return to_virtual(reinterpret_cast(p)); - } + /// Convert a physical address to a virtual one (in the offset-mapped area) + template T * to_virtual(T *p) { + return to_virtual(reinterpret_cast(p)); + } - /// Get the number of pages needed for a given number of bytes. - /// \arg bytes The number of bytes desired - /// \returns The number of pages needed to contain the desired bytes - inline size_t page_count(size_t bytes) { - return ((bytes - 1) >> 12) + 1; - } + /// Get the number of pages needed for a given number of bytes. + /// \arg bytes The number of bytes desired + /// \returns The number of pages needed to contain the desired bytes + inline size_t page_count(size_t bytes) { + return ((bytes - 1) >> 12) + 1; + } - /// Get the given address, aligned to the next lowest page - inline uintptr_t page_align_down(uintptr_t a) { return a & ~(frame_size-1); } + /// Get the given address, aligned to the next lowest page + inline uintptr_t page_align_down(uintptr_t a) { return a & ~(frame_size-1); } - /// Get the given address, aligned to the next page - inline uintptr_t page_align_up(uintptr_t a) { return page_align_down(a-1) + frame_size; } + /// Get the given address, aligned to the next page + inline uintptr_t page_align_up(uintptr_t a) { return page_align_down(a-1) + frame_size; } } // namespace memory diff --git a/src/include/pointer_manipulation.h b/src/include/pointer_manipulation.h index a41e36d..bc9c657 100644 --- a/src/include/pointer_manipulation.h +++ b/src/include/pointer_manipulation.h @@ -9,7 +9,7 @@ /// \tparam S The type pointed to by the `input` pointer template inline T* offset_ptr(S* input, ptrdiff_t offset) { - return reinterpret_cast(reinterpret_cast(input) + offset); + return reinterpret_cast(reinterpret_cast(input) + offset); } /// Iterator for an array of `const T` whose size is known at runtime @@ -19,27 +19,27 @@ template class const_offset_iterator { public: - /// Constructor. - /// \arg t Pointer to the first item in the array - /// \arg off Offset applied to reach successive items. Default is 0, - /// which creates an effectively constant iterator. - const_offset_iterator(T const *t, size_t off=0) : m_t(t), m_off(off) {} + /// Constructor. + /// \arg t Pointer to the first item in the array + /// \arg off Offset applied to reach successive items. Default is 0, + /// which creates an effectively constant iterator. + const_offset_iterator(T const *t, size_t off=0) : m_t(t), m_off(off) {} - const T * operator++() { m_t = offset_ptr(m_t, m_off); return m_t; } - const T * operator++(int) { T* tmp = m_t; operator++(); return tmp; } + const T * operator++() { m_t = offset_ptr(m_t, m_off); return m_t; } + const T * operator++(int) { T* tmp = m_t; operator++(); return tmp; } - bool operator==(T* p) const { return p == m_t; } - bool operator!=(T* p) const { return p != m_t; } - bool operator==(const_offset_iterator &i) const { return i.m_t == m_t; } - bool operator!=(const_offset_iterator &i) const { return i.m_t != m_t; } + bool operator==(T* p) const { return p == m_t; } + bool operator!=(T* p) const { return p != m_t; } + bool operator==(const_offset_iterator &i) const { return i.m_t == m_t; } + bool operator!=(const_offset_iterator &i) const { return i.m_t != m_t; } - const T& operator*() const { return *m_t; } - operator const T& () const { return *m_t; } - const T* operator->() const { return m_t; } + const T& operator*() const { return *m_t; } + operator const T& () const { return *m_t; } + const T* operator->() const { return m_t; } private: - T const *m_t; - size_t m_off; + T const *m_t; + size_t m_off; }; /// iterator for an array of `const T` whose size is known at runtime @@ -49,26 +49,26 @@ template class offset_iterator { public: - /// constructor. - /// \arg t pointer to the first item in the array - /// \arg off offset applied to reach successive items. default is 0, - /// which creates an effectively constant iterator. - offset_iterator(T *t, size_t off=0) : m_t(t), m_off(off) {} + /// constructor. + /// \arg t pointer to the first item in the array + /// \arg off offset applied to reach successive items. default is 0, + /// which creates an effectively constant iterator. + offset_iterator(T *t, size_t off=0) : m_t(t), m_off(off) {} - T * operator++() { m_t = offset_ptr(m_t, m_off); return m_t; } - T * operator++(int) { T* tmp = m_t; operator++(); return tmp; } + T * operator++() { m_t = offset_ptr(m_t, m_off); return m_t; } + T * operator++(int) { T* tmp = m_t; operator++(); return tmp; } - bool operator==(T *p) const { return p == m_t; } - bool operator!=(T *p) const { return p != m_t; } - bool operator==(offset_iterator &i) const { return i.m_t == m_t; } - bool operator!=(offset_iterator &i) const { return i.m_t != m_t; } + bool operator==(T *p) const { return p == m_t; } + bool operator!=(T *p) const { return p != m_t; } + bool operator==(offset_iterator &i) const { return i.m_t == m_t; } + bool operator!=(offset_iterator &i) const { return i.m_t != m_t; } - T & operator*() const { return *m_t; } - operator T & () const { return *m_t; } - T * operator->() const { return m_t; } + T & operator*() const { return *m_t; } + operator T & () const { return *m_t; } + T * operator->() const { return m_t; } private: - T *m_t; - size_t m_off; + T *m_t; + size_t m_off; }; diff --git a/src/kernel/acpi_tables.h b/src/kernel/acpi_tables.h index 22a66f4..641c9f1 100644 --- a/src/kernel/acpi_tables.h +++ b/src/kernel/acpi_tables.h @@ -9,22 +9,22 @@ struct acpi_table_header { - uint32_t type; - uint32_t length; - uint8_t revision; - uint8_t checksum; - char oem_id[6]; - char oem_table[8]; - uint32_t oem_revision; - uint32_t creator_id; - uint32_t creator_revision; + uint32_t type; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem_id[6]; + char oem_table[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; - bool validate(uint32_t expected_type = 0) const; + bool validate(uint32_t expected_type = 0) const; } __attribute__ ((packed)); #define TABLE_HEADER(signature) \ - static constexpr uint32_t type_id = kutil::byteswap(signature); \ - acpi_table_header header; + static constexpr uint32_t type_id = kutil::byteswap(signature); \ + acpi_table_header header; template @@ -33,62 +33,62 @@ bool acpi_validate(const T *t) { return t->header.validate(T::type_id); } template size_t acpi_table_entries(const T *t, size_t size) { - return (t->header.length - sizeof(T)) / size; + return (t->header.length - sizeof(T)) / size; } enum class acpi_gas_type : uint8_t { - system_memory, - system_io, - pci_config, - embedded, - smbus, - platform_channel = 0x0a, - functional_fixed = 0x7f + system_memory, + system_io, + pci_config, + embedded, + smbus, + platform_channel = 0x0a, + functional_fixed = 0x7f }; struct acpi_gas { - acpi_gas_type type; + acpi_gas_type type; - uint8_t reg_bits; - uint8_t reg_offset; - uint8_t access_size; + uint8_t reg_bits; + uint8_t reg_offset; + uint8_t access_size; - uint64_t address; + uint64_t address; } __attribute__ ((packed)); enum class acpi_fadt_flags : uint32_t { - wbinvd = 0x00000001, - wbinvd_flush = 0x00000002, - proc_c1 = 0x00000004, - p_lvl2_up = 0x00000008, - pwr_button = 0x00000010, - slp_button = 0x00000020, - fix_rtc = 0x00000040, - rtc_s4 = 0x00000080, - tmr_val_ext = 0x00000100, - dck_cap = 0x00000200, - reset_reg_sup = 0x00000400, - sealed_case = 0x00000800, - headless = 0x00001000, - cpu_sw_slp = 0x00002000, - pci_exp_wak = 0x00004000, - use_plat_clock = 0x00008000, - s4_rtc_sts_val = 0x00010000, - remote_pwr_cap = 0x00020000, - apic_cluster = 0x00040000, - apic_physical = 0x00080000, - hw_reduced_acpi = 0x00100000, - low_pwr_s0_idle = 0x00200000 + wbinvd = 0x00000001, + wbinvd_flush = 0x00000002, + proc_c1 = 0x00000004, + p_lvl2_up = 0x00000008, + pwr_button = 0x00000010, + slp_button = 0x00000020, + fix_rtc = 0x00000040, + rtc_s4 = 0x00000080, + tmr_val_ext = 0x00000100, + dck_cap = 0x00000200, + reset_reg_sup = 0x00000400, + sealed_case = 0x00000800, + headless = 0x00001000, + cpu_sw_slp = 0x00002000, + pci_exp_wak = 0x00004000, + use_plat_clock = 0x00008000, + s4_rtc_sts_val = 0x00010000, + remote_pwr_cap = 0x00020000, + apic_cluster = 0x00040000, + apic_physical = 0x00080000, + hw_reduced_acpi = 0x00100000, + low_pwr_s0_idle = 0x00200000 }; is_bitfield(acpi_fadt_flags); struct acpi_fadt { - TABLE_HEADER('FACP'); + TABLE_HEADER('FACP'); uint32_t facs; uint32_t dsdt; @@ -136,7 +136,7 @@ struct acpi_fadt acpi_gas reset_reg; uint8_t reset_value; - uint16_t arm_boot_arch; + uint16_t arm_boot_arch; uint8_t fadt_minor_version; @@ -152,60 +152,60 @@ struct acpi_fadt acpi_gas x_gpe0_block; acpi_gas x_gpe1_block; - acpi_gas sleep_control_reg; - acpi_gas sleep_status_reg; + acpi_gas sleep_control_reg; + acpi_gas sleep_status_reg; - uint64_t hypervisor_vendor_id; + uint64_t hypervisor_vendor_id; } __attribute__ ((packed)); struct acpi_xsdt { - TABLE_HEADER('XSDT'); - acpi_table_header *headers[0]; + TABLE_HEADER('XSDT'); + acpi_table_header *headers[0]; } __attribute__ ((packed)); struct acpi_apic { - TABLE_HEADER('APIC'); - uint32_t local_address; - uint32_t flags; - uint8_t controller_data[0]; + TABLE_HEADER('APIC'); + uint32_t local_address; + uint32_t flags; + uint8_t controller_data[0]; } __attribute__ ((packed)); struct acpi_mcfg_entry { - uint64_t base; - uint16_t group; - uint8_t bus_start; - uint8_t bus_end; - uint32_t reserved; + uint64_t base; + uint16_t group; + uint8_t bus_start; + uint8_t bus_end; + uint32_t reserved; } __attribute__ ((packed)); struct acpi_mcfg { - TABLE_HEADER('MCFG'); - uint64_t reserved; - acpi_mcfg_entry entries[0]; + TABLE_HEADER('MCFG'); + uint64_t reserved; + acpi_mcfg_entry entries[0]; } __attribute__ ((packed)); struct acpi_hpet { - TABLE_HEADER('HPET'); - uint32_t hardware_id; - acpi_gas base_address; - uint8_t index; - uint16_t periodic_min; - uint8_t attributes; + TABLE_HEADER('HPET'); + uint32_t hardware_id; + acpi_gas base_address; + uint8_t index; + uint16_t periodic_min; + uint8_t attributes; } __attribute__ ((packed)); struct acpi_bgrt { - TABLE_HEADER('BGRT'); - uint16_t version; - uint8_t status; - uint8_t type; - uintptr_t address; - uint32_t offset_x; - uint32_t offset_y; + TABLE_HEADER('BGRT'); + uint16_t version; + uint8_t status; + uint8_t type; + uintptr_t address; + uint32_t offset_x; + uint32_t offset_y; } __attribute__ ((packed)); diff --git a/src/kernel/apic.cpp b/src/kernel/apic.cpp index 35d9f3e..9965647 100644 --- a/src/kernel/apic.cpp +++ b/src/kernel/apic.cpp @@ -26,286 +26,286 @@ static constexpr uint16_t lapic_timer_div = 0x03e0; static uint32_t apic_read(uint32_t volatile *apic, uint16_t offset) { - return *(apic + offset/sizeof(uint32_t)); + return *(apic + offset/sizeof(uint32_t)); } static void apic_write(uint32_t volatile *apic, uint16_t offset, uint32_t value) { - log::debug(logs::apic, "LAPIC write: %x = %08lx", offset, value); - *(apic + offset/sizeof(uint32_t)) = value; + log::debug(logs::apic, "LAPIC write: %x = %08lx", offset, value); + *(apic + offset/sizeof(uint32_t)) = value; } static uint32_t ioapic_read(uint32_t volatile *base, uint8_t reg) { - *base = reg; - return *(base + 4); + *base = reg; + return *(base + 4); } static void ioapic_write(uint32_t volatile *base, uint8_t reg, uint32_t value) { - *base = reg; - *(base + 4) = value; + *base = reg; + *(base + 4) = value; } apic::apic(uintptr_t base) : - m_base(memory::to_virtual(base)) + m_base(memory::to_virtual(base)) { } lapic::lapic(uintptr_t base) : - apic(base), - m_divisor(0) + apic(base), + m_divisor(0) { - apic_write(m_base, lapic_lvt_error, static_cast(isr::isrAPICError)); - apic_write(m_base, lapic_spurious, static_cast(isr::isrSpurious)); + apic_write(m_base, lapic_lvt_error, static_cast(isr::isrAPICError)); + apic_write(m_base, lapic_spurious, static_cast(isr::isrSpurious)); } uint8_t lapic::get_id() { - return static_cast(apic_read(m_base, lapic_id) >> 24); + return static_cast(apic_read(m_base, lapic_id) >> 24); } void lapic::send_ipi(ipi mode, uint8_t vector, uint8_t dest) { - // Wait until the APIC is ready to send - ipi_wait(); + // Wait until the APIC is ready to send + ipi_wait(); - uint32_t command = - static_cast(vector) | - static_cast(mode); + uint32_t command = + static_cast(vector) | + static_cast(mode); - apic_write(m_base, lapic_icr_high, static_cast(dest) << 24); - apic_write(m_base, lapic_icr_low, command); + apic_write(m_base, lapic_icr_high, static_cast(dest) << 24); + apic_write(m_base, lapic_icr_low, command); } void lapic::send_ipi_broadcast(ipi mode, bool self, uint8_t vector) { - // Wait until the APIC is ready to send - ipi_wait(); + // Wait until the APIC is ready to send + ipi_wait(); - uint32_t command = - static_cast(vector) | - static_cast(mode) | - (self ? 0 : (1 << 18)) | - (1 << 19); + uint32_t command = + static_cast(vector) | + static_cast(mode) | + (self ? 0 : (1 << 18)) | + (1 << 19); - apic_write(m_base, lapic_icr_high, 0); - apic_write(m_base, lapic_icr_low, command); + apic_write(m_base, lapic_icr_high, 0); + apic_write(m_base, lapic_icr_low, command); } void lapic::ipi_wait() { - while (apic_read(m_base, lapic_icr_low) & (1<<12)) - asm volatile ("pause" : : : "memory"); + while (apic_read(m_base, lapic_icr_low) & (1<<12)) + asm volatile ("pause" : : : "memory"); } void lapic::calibrate_timer() { - interrupts_disable(); + interrupts_disable(); - log::info(logs::apic, "Calibrating APIC timer..."); + log::info(logs::apic, "Calibrating APIC timer..."); - const uint32_t initial = -1u; - enable_timer(isr::isrSpurious); - set_divisor(1); - apic_write(m_base, lapic_timer_init, initial); + const uint32_t initial = -1u; + enable_timer(isr::isrSpurious); + set_divisor(1); + apic_write(m_base, lapic_timer_init, initial); - uint64_t us = 20000; - clock::get().spinwait(us); + uint64_t us = 20000; + clock::get().spinwait(us); - uint32_t remaining = apic_read(m_base, lapic_timer_cur); - uint64_t ticks_total = initial - remaining; - s_ticks_per_us = ticks_total / us; + uint32_t remaining = apic_read(m_base, lapic_timer_cur); + uint64_t ticks_total = initial - remaining; + s_ticks_per_us = ticks_total / us; - log::info(logs::apic, "APIC timer ticks %d times per microsecond.", s_ticks_per_us); + log::info(logs::apic, "APIC timer ticks %d times per microsecond.", s_ticks_per_us); - interrupts_enable(); + interrupts_enable(); } void lapic::set_divisor(uint8_t divisor) { - uint32_t divbits = 0; + uint32_t divbits = 0; - switch (divisor) { - case 1: divbits = 0xb; break; - case 2: divbits = 0x0; break; - case 4: divbits = 0x1; break; - case 8: divbits = 0x2; break; - case 16: divbits = 0x3; break; - case 32: divbits = 0x8; break; - case 64: divbits = 0x9; break; - case 128: divbits = 0xa; break; - default: - kassert(0, "Invalid divisor passed to lapic::set_divisor"); - } + switch (divisor) { + case 1: divbits = 0xb; break; + case 2: divbits = 0x0; break; + case 4: divbits = 0x1; break; + case 8: divbits = 0x2; break; + case 16: divbits = 0x3; break; + case 32: divbits = 0x8; break; + case 64: divbits = 0x9; break; + case 128: divbits = 0xa; break; + default: + kassert(0, "Invalid divisor passed to lapic::set_divisor"); + } - apic_write(m_base, lapic_timer_div, divbits); - m_divisor = divisor; + apic_write(m_base, lapic_timer_div, divbits); + m_divisor = divisor; } void lapic::enable_timer(isr vector, bool repeat) { - uint32_t lvte = static_cast(vector); - if (repeat) - lvte |= 0x20000; - apic_write(m_base, lapic_lvt_timer, lvte); + uint32_t lvte = static_cast(vector); + if (repeat) + lvte |= 0x20000; + apic_write(m_base, lapic_lvt_timer, lvte); - log::debug(logs::apic, "Enabling APIC timer at isr %02x", vector); + log::debug(logs::apic, "Enabling APIC timer at isr %02x", vector); } uint32_t lapic::reset_timer(uint64_t interval) { - uint64_t remaining = ticks_to_us(apic_read(m_base, lapic_timer_cur)); - uint64_t ticks = us_to_ticks(interval); + uint64_t remaining = ticks_to_us(apic_read(m_base, lapic_timer_cur)); + uint64_t ticks = us_to_ticks(interval); - int divisor = 1; - while (ticks > 0xffffffffull) { - ticks >>= 1; - divisor <<= 1; - } + int divisor = 1; + while (ticks > 0xffffffffull) { + ticks >>= 1; + divisor <<= 1; + } - if (divisor != m_divisor) - set_divisor(divisor); + if (divisor != m_divisor) + set_divisor(divisor); - apic_write(m_base, lapic_timer_init, ticks); - return remaining; + apic_write(m_base, lapic_timer_init, ticks); + return remaining; } void lapic::enable_lint(uint8_t num, isr vector, bool nmi, uint16_t flags) { - kassert(num == 0 || num == 1, "Invalid LINT passed to lapic::enable_lint."); + kassert(num == 0 || num == 1, "Invalid LINT passed to lapic::enable_lint."); - uint16_t off = num ? lapic_lvt_lint1 : lapic_lvt_lint0; - uint32_t lvte = static_cast(vector); + uint16_t off = num ? lapic_lvt_lint1 : lapic_lvt_lint0; + uint32_t lvte = static_cast(vector); - uint16_t polarity = flags & 0x3; - if (polarity == 3) - lvte |= (1 << 13); + uint16_t polarity = flags & 0x3; + if (polarity == 3) + lvte |= (1 << 13); - uint16_t trigger = (flags >> 2) & 0x3; - if (trigger == 3) - lvte |= (1 << 15); + uint16_t trigger = (flags >> 2) & 0x3; + if (trigger == 3) + lvte |= (1 << 15); - apic_write(m_base, off, lvte); - log::debug(logs::apic, "APIC LINT%d enabled as %s %d %s-triggered, active %s.", - num, nmi ? "NMI" : "ISR", vector, - polarity == 3 ? "level" : "edge", - trigger == 3 ? "low" : "high"); + apic_write(m_base, off, lvte); + log::debug(logs::apic, "APIC LINT%d enabled as %s %d %s-triggered, active %s.", + num, nmi ? "NMI" : "ISR", vector, + polarity == 3 ? "level" : "edge", + trigger == 3 ? "low" : "high"); } void lapic::enable() { - apic_write(m_base, lapic_spurious, - apic_read(m_base, lapic_spurious) | 0x100); - log::debug(logs::apic, "LAPIC enabled!"); + apic_write(m_base, lapic_spurious, + apic_read(m_base, lapic_spurious) | 0x100); + log::debug(logs::apic, "LAPIC enabled!"); } void lapic::disable() { - apic_write(m_base, lapic_spurious, - apic_read(m_base, lapic_spurious) & ~0x100); - log::debug(logs::apic, "LAPIC disabled."); + apic_write(m_base, lapic_spurious, + apic_read(m_base, lapic_spurious) & ~0x100); + log::debug(logs::apic, "LAPIC disabled."); } ioapic::ioapic(uintptr_t base, uint32_t base_gsi) : - apic(base), - m_base_gsi(base_gsi) + apic(base), + m_base_gsi(base_gsi) { - uint32_t id = ioapic_read(m_base, 0); - uint32_t version = ioapic_read(m_base, 1); + uint32_t id = ioapic_read(m_base, 0); + uint32_t version = ioapic_read(m_base, 1); - m_id = (id >> 24) & 0xff; - m_version = version & 0xff; - m_num_gsi = (version >> 16) & 0xff; - log::debug(logs::apic, "IOAPIC %d loaded, version %d, GSIs %d-%d", - m_id, m_version, base_gsi, base_gsi + (m_num_gsi - 1)); + m_id = (id >> 24) & 0xff; + m_version = version & 0xff; + m_num_gsi = (version >> 16) & 0xff; + log::debug(logs::apic, "IOAPIC %d loaded, version %d, GSIs %d-%d", + m_id, m_version, base_gsi, base_gsi + (m_num_gsi - 1)); - for (uint8_t i = 0; i < m_num_gsi; ++i) { - uint16_t flags = (i < 0x10) ? 0 : 0xf; - isr vector = isr::irq00 + i; - redirect(i, vector, flags, true); - } + for (uint8_t i = 0; i < m_num_gsi; ++i) { + uint16_t flags = (i < 0x10) ? 0 : 0xf; + isr vector = isr::irq00 + i; + redirect(i, vector, flags, true); + } } void ioapic::redirect(uint8_t irq, isr vector, uint16_t flags, bool masked) { - log::debug(logs::apic, "IOAPIC %d redirecting irq %3d to vector %3d [%04x]%s", - m_id, irq, vector, flags, masked ? " (masked)" : ""); + log::debug(logs::apic, "IOAPIC %d redirecting irq %3d to vector %3d [%04x]%s", + m_id, irq, vector, flags, masked ? " (masked)" : ""); - uint64_t entry = static_cast(vector); + uint64_t entry = static_cast(vector); - uint16_t polarity = flags & 0x3; - if (polarity == 3) - entry |= (1 << 13); + uint16_t polarity = flags & 0x3; + if (polarity == 3) + entry |= (1 << 13); - uint16_t trigger = (flags >> 2) & 0x3; - if (trigger == 3) - entry |= (1 << 15); + uint16_t trigger = (flags >> 2) & 0x3; + if (trigger == 3) + entry |= (1 << 15); - if (masked) - entry |= (1 << 16); + if (masked) + entry |= (1 << 16); - ioapic_write(m_base, (2 * irq) + 0x10, static_cast(entry & 0xffffffff)); - ioapic_write(m_base, (2 * irq) + 0x11, static_cast(entry >> 32)); + ioapic_write(m_base, (2 * irq) + 0x10, static_cast(entry & 0xffffffff)); + ioapic_write(m_base, (2 * irq) + 0x11, static_cast(entry >> 32)); } void ioapic::mask(uint8_t irq, bool masked) { - log::debug(logs::apic, "IOAPIC %d %smasking irq %3d", - m_id, masked ? "" : "un", irq); + log::debug(logs::apic, "IOAPIC %d %smasking irq %3d", + m_id, masked ? "" : "un", irq); - uint32_t entry = ioapic_read(m_base, (2 * irq) + 0x10); - if (masked) - entry |= (1 << 16); - else - entry &= ~(1 << 16); + uint32_t entry = ioapic_read(m_base, (2 * irq) + 0x10); + if (masked) + entry |= (1 << 16); + else + entry &= ~(1 << 16); - ioapic_write(m_base, (2 * irq) + 0x10, entry); + ioapic_write(m_base, (2 * irq) + 0x10, entry); } void ioapic::dump_redirs() const { - log::debug(logs::apic, "IOAPIC %d redirections:", m_id); + log::debug(logs::apic, "IOAPIC %d redirections:", m_id); - for (uint8_t i = 0; i < m_num_gsi; ++i) { - uint64_t low = ioapic_read(m_base, 0x10 + (2 *i)); - uint64_t high = ioapic_read(m_base, 0x10 + (2 *i)); - uint64_t redir = low | (high << 32); - if (redir == 0) continue; + for (uint8_t i = 0; i < m_num_gsi; ++i) { + uint64_t low = ioapic_read(m_base, 0x10 + (2 *i)); + uint64_t high = ioapic_read(m_base, 0x10 + (2 *i)); + uint64_t redir = low | (high << 32); + if (redir == 0) continue; - uint8_t vector = redir & 0xff; - uint8_t mode = (redir >> 8) & 0x7; - uint8_t dest_mode = (redir >> 11) & 0x1; - uint8_t polarity = (redir >> 13) & 0x1; - uint8_t trigger = (redir >> 15) & 0x1; - uint8_t mask = (redir >> 16) & 0x1; - uint8_t dest = (redir >> 56) & 0xff; + uint8_t vector = redir & 0xff; + uint8_t mode = (redir >> 8) & 0x7; + uint8_t dest_mode = (redir >> 11) & 0x1; + uint8_t polarity = (redir >> 13) & 0x1; + uint8_t trigger = (redir >> 15) & 0x1; + uint8_t mask = (redir >> 16) & 0x1; + uint8_t dest = (redir >> 56) & 0xff; - log::debug(logs::apic, " %2d: vec %3d %s active, %s-triggered %s dest %d: %x", - m_base_gsi + i, vector, - polarity ? "low" : "high", - trigger ? "level" : "edge", - mask ? "masked" : "", - dest_mode, - dest); - } + log::debug(logs::apic, " %2d: vec %3d %s active, %s-triggered %s dest %d: %x", + m_base_gsi + i, vector, + polarity ? "low" : "high", + trigger ? "level" : "edge", + mask ? "masked" : "", + dest_mode, + dest); + } } diff --git a/src/kernel/apic.h b/src/kernel/apic.h index 8c05349..912f265 100644 --- a/src/kernel/apic.h +++ b/src/kernel/apic.h @@ -11,137 +11,137 @@ enum class isr : uint8_t; class apic { public: - /// Constructor - /// \arg base Physical base address of the APIC's MMIO registers - apic(uintptr_t base); + /// Constructor + /// \arg base Physical base address of the APIC's MMIO registers + apic(uintptr_t base); protected: - uint32_t *m_base; + uint32_t *m_base; }; /// Controller for processor-local APICs class lapic : - public apic + public apic { public: - /// Constructor - /// \arg base Physicl base address of the APIC's MMIO registers - lapic(uintptr_t base); + /// Constructor + /// \arg base Physicl base address of the APIC's MMIO registers + lapic(uintptr_t base); - /// Get the local APIC's ID - uint8_t get_id(); + /// Get the local APIC's ID + uint8_t get_id(); - enum class ipi : uint32_t - { - // Delivery modes - fixed = 0x0000, - smi = 0x0200, - nmi = 0x0400, - init = 0x0500, - startup = 0x0600, + enum class ipi : uint32_t + { + // Delivery modes + fixed = 0x0000, + smi = 0x0200, + nmi = 0x0400, + init = 0x0500, + startup = 0x0600, - // Flags - deassert = 0x0000, - assert = 0x4000, - edge = 0x0000, ///< edge-triggered - level = 0x8000, ///< level-triggered - }; + // Flags + deassert = 0x0000, + assert = 0x4000, + edge = 0x0000, ///< edge-triggered + level = 0x8000, ///< level-triggered + }; - /// Send an inter-processor interrupt. - /// \arg mode The sending mode - /// \arg vector The interrupt vector - /// \arg dest The APIC ID of the destination - void send_ipi(ipi mode, uint8_t vector, uint8_t dest); + /// Send an inter-processor interrupt. + /// \arg mode The sending mode + /// \arg vector The interrupt vector + /// \arg dest The APIC ID of the destination + void send_ipi(ipi mode, uint8_t vector, uint8_t dest); - /// Send an inter-processor broadcast interrupt to all other CPUs - /// \arg mode The sending mode - /// \arg self If true, include this CPU in the broadcast - /// \arg vector The interrupt vector - void send_ipi_broadcast(ipi mode, bool self, uint8_t vector); + /// Send an inter-processor broadcast interrupt to all other CPUs + /// \arg mode The sending mode + /// \arg self If true, include this CPU in the broadcast + /// \arg vector The interrupt vector + void send_ipi_broadcast(ipi mode, bool self, uint8_t vector); - /// Wait for an IPI to finish sending. This is done automatically - /// before sending another IPI with send_ipi(). - void ipi_wait(); + /// Wait for an IPI to finish sending. This is done automatically + /// before sending another IPI with send_ipi(). + void ipi_wait(); - /// Enable interrupts for the LAPIC timer. - /// \arg vector Interrupt vector the timer should use - /// \arg repeat If false, this timer is one-off, otherwise repeating - void enable_timer(isr vector, bool repeat = true); + /// Enable interrupts for the LAPIC timer. + /// \arg vector Interrupt vector the timer should use + /// \arg repeat If false, this timer is one-off, otherwise repeating + void enable_timer(isr vector, bool repeat = true); - /// Reset the timer countdown. - /// \arg interval The interval in us before an interrupt, or 0 to stop the timer - /// \returns The interval in us that was remaining before reset - uint32_t reset_timer(uint64_t interval); + /// Reset the timer countdown. + /// \arg interval The interval in us before an interrupt, or 0 to stop the timer + /// \returns The interval in us that was remaining before reset + uint32_t reset_timer(uint64_t interval); - /// Stop the timer. - /// \returns The interval in us remaining before an interrupt was to happen - inline uint32_t stop_timer() { return reset_timer(0); } + /// Stop the timer. + /// \returns The interval in us remaining before an interrupt was to happen + inline uint32_t stop_timer() { return reset_timer(0); } - /// Enable interrupts for the LAPIC LINT0 pin. - /// \arg num Local interrupt number (0 or 1) - /// \arg vector Interrupt vector LINT0 should use - /// \arg nmi Whether this interrupt is NMI delivery mode - /// \arg flags Flags for mode/polarity (ACPI MPS INTI flags) - void enable_lint(uint8_t num, isr vector, bool nmi, uint16_t flags); + /// Enable interrupts for the LAPIC LINT0 pin. + /// \arg num Local interrupt number (0 or 1) + /// \arg vector Interrupt vector LINT0 should use + /// \arg nmi Whether this interrupt is NMI delivery mode + /// \arg flags Flags for mode/polarity (ACPI MPS INTI flags) + void enable_lint(uint8_t num, isr vector, bool nmi, uint16_t flags); - void enable(); ///< Enable servicing of interrupts - void disable(); ///< Disable (temporarily) servicing of interrupts + void enable(); ///< Enable servicing of interrupts + void disable(); ///< Disable (temporarily) servicing of interrupts - /// Calibrate the timer speed against the clock - void calibrate_timer(); + /// Calibrate the timer speed against the clock + void calibrate_timer(); private: - inline static uint64_t ticks_to_us(uint64_t ticks) { return ticks / s_ticks_per_us; } - inline static uint64_t us_to_ticks(uint64_t interval) { return interval * s_ticks_per_us; } + inline static uint64_t ticks_to_us(uint64_t ticks) { return ticks / s_ticks_per_us; } + inline static uint64_t us_to_ticks(uint64_t interval) { return interval * s_ticks_per_us; } - void set_divisor(uint8_t divisor); - void set_repeat(bool repeat); + void set_divisor(uint8_t divisor); + void set_repeat(bool repeat); - uint32_t m_divisor; - static uint64_t s_ticks_per_us; + uint32_t m_divisor; + static uint64_t s_ticks_per_us; }; /// Controller for I/O APICs class ioapic : - public apic + public apic { public: - /// Constructor - /// \arg base Physical base address of the APIC's MMIO registers - /// \arg base_gsi Starting global system interrupt number of this IOAPIC - ioapic(uintptr_t base, uint32_t base_gsi); + /// Constructor + /// \arg base Physical base address of the APIC's MMIO registers + /// \arg base_gsi Starting global system interrupt number of this IOAPIC + ioapic(uintptr_t base, uint32_t base_gsi); - uint32_t get_base_gsi() const { return m_base_gsi; } - uint32_t get_num_gsi() const { return m_num_gsi; } + uint32_t get_base_gsi() const { return m_base_gsi; } + uint32_t get_num_gsi() const { return m_num_gsi; } - /// Set a redirection entry. - /// TODO: pick CPU - /// \arg source Source interrupt number - /// \arg vector Interrupt vector that should be used - /// \arg flags Flags for mode/polarity (ACPI MPS INTI flags) - /// \arg masked Whether the iterrupt should be suppressed - void redirect(uint8_t irq, isr vector, uint16_t flags, bool masked); + /// Set a redirection entry. + /// TODO: pick CPU + /// \arg source Source interrupt number + /// \arg vector Interrupt vector that should be used + /// \arg flags Flags for mode/polarity (ACPI MPS INTI flags) + /// \arg masked Whether the iterrupt should be suppressed + void redirect(uint8_t irq, isr vector, uint16_t flags, bool masked); - /// Mask or unmask an interrupt to stop/start having it sent to the CPU - /// \arg irq The IOAPIC-local irq number - /// \arg masked Whether to suppress this interrupt - void mask(uint8_t irq, bool masked); + /// Mask or unmask an interrupt to stop/start having it sent to the CPU + /// \arg irq The IOAPIC-local irq number + /// \arg masked Whether to suppress this interrupt + void mask(uint8_t irq, bool masked); - /// Mask all interrupts on this IOAPIC. - void mask_all() { for(int i=0; iwrite(*fgseq++); - } + if (m_serial) { + const char *fgseq = "\x1b[2J"; + while (*fgseq) + m_serial->write(*fgseq++); + } } void console::echo() { - putc(m_serial->read()); + putc(m_serial->read()); } void console::set_color(uint8_t fg, uint8_t bg) { - if (m_serial) { - const char *fgseq = "\x1b[38;5;"; - while (*fgseq) - m_serial->write(*fgseq++); - if (fg >= 100) m_serial->write('0' + (fg/100)); - if (fg >= 10) m_serial->write('0' + (fg/10) % 10); - m_serial->write('0' + fg % 10); - m_serial->write('m'); + if (m_serial) { + const char *fgseq = "\x1b[38;5;"; + while (*fgseq) + m_serial->write(*fgseq++); + if (fg >= 100) m_serial->write('0' + (fg/100)); + if (fg >= 10) m_serial->write('0' + (fg/10) % 10); + m_serial->write('0' + fg % 10); + m_serial->write('m'); - const char *bgseq = "\x1b[48;5;"; - while (*bgseq) - m_serial->write(*bgseq++); - if (bg >= 100) m_serial->write('0' + (bg/100)); - if (bg >= 10) m_serial->write('0' + (bg/10) % 10); - m_serial->write('0' + bg % 10); - m_serial->write('m'); - } + const char *bgseq = "\x1b[48;5;"; + while (*bgseq) + m_serial->write(*bgseq++); + if (bg >= 100) m_serial->write('0' + (bg/100)); + if (bg >= 10) m_serial->write('0' + (bg/10) % 10); + m_serial->write('0' + bg % 10); + m_serial->write('m'); + } } size_t console::puts(const char *message) { - size_t n = 0; - while (message && *message) { - n++; - putc(*message++); - } + size_t n = 0; + while (message && *message) { + n++; + putc(*message++); + } - return n; + return n; } void console::putc(char c) { - if (m_serial) { - if (c == '\n') m_serial->write('\r'); - m_serial->write(c); - } + if (m_serial) { + if (c == '\n') m_serial->write('\r'); + m_serial->write(c); + } } void console::vprintf(const char *fmt, va_list args) { - static const unsigned buf_size = 256; - char buffer[buf_size]; - vsnprintf_(buffer, buf_size, fmt, args); - puts(buffer); + static const unsigned buf_size = 256; + char buffer[buf_size]; + vsnprintf_(buffer, buf_size, fmt, args); + puts(buffer); } diff --git a/src/kernel/console.h b/src/kernel/console.h index 5b3c8ba..df10394 100644 --- a/src/kernel/console.h +++ b/src/kernel/console.h @@ -8,35 +8,35 @@ class serial_port; class console { public: - console(); - console(serial_port *serial); + console(); + console(serial_port *serial); - void set_color(uint8_t fg = 7, uint8_t bg = 0); + void set_color(uint8_t fg = 7, uint8_t bg = 0); - void putc(char c); - size_t puts(const char *message); - void vprintf(const char *fmt, va_list args); + void putc(char c); + size_t puts(const char *message); + void vprintf(const char *fmt, va_list args); - inline void printf(const char *fmt, ...) - { - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - } + inline void printf(const char *fmt, ...) + { + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + } - template - void put_hex(T x, int width = 0, char pad = ' '); + template + void put_hex(T x, int width = 0, char pad = ' '); - template - void put_dec(T x, int width = 0, char pad = ' '); + template + void put_dec(T x, int width = 0, char pad = ' '); - void echo(); + void echo(); - static console * get(); + static console * get(); private: - serial_port *m_serial; + serial_port *m_serial; }; extern console &g_console; @@ -48,37 +48,37 @@ extern const char digits[]; template void console::put_hex(T x, int width, char pad) { - static const int chars = sizeof(x) * 2; - char message[chars + 1]; + static const int chars = sizeof(x) * 2; + char message[chars + 1]; - int len = 1; - for (int i = chars - 1; i >= 0; --i) { - uint8_t nibble = (x >> (i*4)) & 0xf; - if (nibble) len = len > i + 1 ? len : i + 1; - message[chars - i - 1] = digits[nibble]; - } - message[chars] = 0; + int len = 1; + for (int i = chars - 1; i >= 0; --i) { + uint8_t nibble = (x >> (i*4)) & 0xf; + if (nibble) len = len > i + 1 ? len : i + 1; + message[chars - i - 1] = digits[nibble]; + } + message[chars] = 0; - if (width > len) for(int i=0; i<(width-len); ++i) putc(pad); - puts(message + (chars - len)); - if (-width > len) for(int i=0; i<(-width-len); ++i) putc(' '); + if (width > len) for(int i=0; i<(width-len); ++i) putc(pad); + puts(message + (chars - len)); + if (-width > len) for(int i=0; i<(-width-len); ++i) putc(' '); } template void console::put_dec(T x, int width, char pad) { - static const int chars = sizeof(x) * 3; - char message[chars + 1]; - char *p = message + chars; - int length = 0; - *p-- = 0; - do { - *p-- = digits[x % 10]; - x /= 10; - length += 1; - } while (x != 0); + static const int chars = sizeof(x) * 3; + char message[chars + 1]; + char *p = message + chars; + int length = 0; + *p-- = 0; + do { + *p-- = digits[x % 10]; + x /= 10; + length += 1; + } while (x != 0); - if (width > length) for(int i=0; i<(width-length); ++i) putc(pad); - puts(++p); - if (-width > length) for(int i=0; i<(-width-length); ++i) putc(' '); + if (width > length) for(int i=0; i<(width-length); ++i) putc(pad); + puts(++p); + if (-width > length) for(int i=0; i<(-width-length); ++i) putc(' '); } diff --git a/src/kernel/cpprt.cpp b/src/kernel/cpprt.cpp index ca4e3e7..1efbfb4 100644 --- a/src/kernel/cpprt.cpp +++ b/src/kernel/cpprt.cpp @@ -3,17 +3,17 @@ using __exit_func = void (*)(void *); extern "C" { - void *__dso_handle __attribute__ ((__weak__)); - int __cxa_atexit(__exit_func, void *, void *); - void __cxa_pure_virtual(); + void *__dso_handle __attribute__ ((__weak__)); + int __cxa_atexit(__exit_func, void *, void *); + void __cxa_pure_virtual(); } struct __exit_func_entry { - __exit_func func; - void *obj; - void *dso; + __exit_func func; + void *obj; + void *dso; }; static int __num_exit_funcs = 0; @@ -23,15 +23,15 @@ __exit_func_entry __exit_funcs[__max_exit_funcs]; int __cxa_atexit(__exit_func f, void *o, void *dso) { - int i = __num_exit_funcs++; - if (i >= __max_exit_funcs) return -1; - __exit_funcs[i].func = f; - __exit_funcs[i].obj = o; - __exit_funcs[i].dso = dso; - return 0; + int i = __num_exit_funcs++; + if (i >= __max_exit_funcs) return -1; + __exit_funcs[i].func = f; + __exit_funcs[i].obj = o; + __exit_funcs[i].dso = dso; + return 0; } void __cxa_pure_virtual() { - kassert(0, "Pure virtual function call"); + kassert(0, "Pure virtual function call"); } diff --git a/src/kernel/cpu.cpp b/src/kernel/cpu.cpp index a485264..ae8ed55 100644 --- a/src/kernel/cpu.cpp +++ b/src/kernel/cpu.cpp @@ -18,20 +18,20 @@ cpu_data g_bsp_cpu_data; void cpu_validate() { - cpu::cpu_id cpu; + cpu::cpu_id cpu; - log::info(logs::boot, "CPU: %s", cpu.brand_name()); - log::debug(logs::boot, " Vendor is %s", cpu.vendor_id()); + log::info(logs::boot, "CPU: %s", cpu.brand_name()); + log::debug(logs::boot, " Vendor is %s", cpu.vendor_id()); - log::debug(logs::boot, " Higest basic CPUID: 0x%02x", cpu.highest_basic()); - log::debug(logs::boot, " Higest ext CPUID: 0x%02x", cpu.highest_ext() & ~cpu::cpu_id::cpuid_extended); + log::debug(logs::boot, " Higest basic CPUID: 0x%02x", cpu.highest_basic()); + log::debug(logs::boot, " Higest ext CPUID: 0x%02x", cpu.highest_ext() & ~cpu::cpu_id::cpuid_extended); #define CPU_FEATURE_OPT(name, ...) \ - log::debug(logs::boot, " Supports %9s: %s", #name, cpu.has_feature(cpu::feature::name) ? "yes" : "no"); + log::debug(logs::boot, " Supports %9s: %s", #name, cpu.has_feature(cpu::feature::name) ? "yes" : "no"); #define CPU_FEATURE_REQ(name, feat_leaf, feat_sub, regname, bit) \ - CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit); \ - kassert(cpu.has_feature(cpu::feature::name), "Missing required CPU feature " #name ); + CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit); \ + kassert(cpu.has_feature(cpu::feature::name), "Missing required CPU feature " #name ); #include "cpu/features.inc" #undef CPU_FEATURE_OPT @@ -41,32 +41,32 @@ cpu_validate() void cpu_early_init(cpu_data *cpu) { - cpu->idt->install(); - cpu->gdt->install(); + cpu->idt->install(); + cpu->gdt->install(); - // Install the GS base pointint to the cpu_data - wrmsr(msr::ia32_gs_base, reinterpret_cast(cpu)); + // Install the GS base pointint to the cpu_data + wrmsr(msr::ia32_gs_base, reinterpret_cast(cpu)); - // Set the initial process as the kernel "process" - extern process &g_kernel_process; - cpu->process = &g_kernel_process; + // Set the initial process as the kernel "process" + extern process &g_kernel_process; + cpu->process = &g_kernel_process; } void cpu_init(cpu_data *cpu, bool bsp) { - if (!bsp) { - // The BSP already called cpu_early_init - cpu_early_init(cpu); - } + if (!bsp) { + // The BSP already called cpu_early_init + cpu_early_init(cpu); + } - // Set up the syscall MSRs - syscall_enable(); + // Set up the syscall MSRs + syscall_enable(); - // Set up the page attributes table - uint64_t pat = rdmsr(msr::ia32_pat); - pat = (pat & 0x00ffffffffffffffull) | (0x01ull << 56); // set PAT 7 to WC - wrmsr(msr::ia32_pat, pat); + // Set up the page attributes table + uint64_t pat = rdmsr(msr::ia32_pat); + pat = (pat & 0x00ffffffffffffffull) | (0x01ull << 56); // set PAT 7 to WC + wrmsr(msr::ia32_pat, pat); - cpu->idt->add_ist_entries(); + cpu->idt->add_ist_entries(); } diff --git a/src/kernel/cpu.h b/src/kernel/cpu.h index 9e5ab01..1efbc2a 100644 --- a/src/kernel/cpu.h +++ b/src/kernel/cpu.h @@ -12,32 +12,32 @@ class TSS; struct cpu_state { - uint64_t r15, r14, r13, r12, r11, r10, r9, r8; - uint64_t rdi, rsi, rbp, rbx, rdx, rcx, rax; - uint64_t interrupt, errorcode; - uint64_t rip, cs, rflags, rsp, ss; + uint64_t r15, r14, r13, r12, r11, r10, r9, r8; + uint64_t rdi, rsi, rbp, rbx, rdx, rcx, rax; + uint64_t interrupt, errorcode; + uint64_t rip, cs, rflags, rsp, ss; }; /// Per-cpu state data. If you change this, remember to update the assembly /// version in 'tasking.inc' struct cpu_data { - cpu_data *self; - uint16_t id; - uint16_t index; - uint32_t reserved; - uintptr_t rsp0; - uintptr_t rsp3; - TCB *tcb; - thread *thread; - process *process; - IDT *idt; - TSS *tss; - GDT *gdt; + cpu_data *self; + uint16_t id; + uint16_t index; + uint32_t reserved; + uintptr_t rsp0; + uintptr_t rsp3; + TCB *tcb; + thread *thread; + process *process; + IDT *idt; + TSS *tss; + GDT *gdt; - // Members beyond this point do not appear in - // the assembly version - lapic *apic; + // Members beyond this point do not appear in + // the assembly version + lapic *apic; }; extern "C" cpu_data * _current_gsbase(); diff --git a/src/kernel/debug.cpp b/src/kernel/debug.cpp index e848055..bbafcb5 100644 --- a/src/kernel/debug.cpp +++ b/src/kernel/debug.cpp @@ -11,63 +11,63 @@ size_t __counter_syscall_sysret = 0; void print_regs(const cpu_state ®s) { - console *cons = console::get(); - cpu_data &cpu = current_cpu(); + console *cons = console::get(); + cpu_data &cpu = current_cpu(); - uint64_t cr2 = 0; - __asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2)); + uint64_t cr2 = 0; + __asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2)); - uintptr_t cr3 = 0; - __asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (cr3) ); + uintptr_t cr3 = 0; + __asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (cr3) ); - cons->printf(" process: %llx", cpu.process->koid()); - cons->printf(" thread: %llx\n", cpu.thread->koid()); + cons->printf(" process: %llx", cpu.process->koid()); + cons->printf(" thread: %llx\n", cpu.thread->koid()); - print_regL("rax", regs.rax); - print_regM("rbx", regs.rbx); - print_regR("rcx", regs.rcx); - print_regL("rdx", regs.rdx); - print_regM("rdi", regs.rdi); - print_regR("rsi", regs.rsi); + print_regL("rax", regs.rax); + print_regM("rbx", regs.rbx); + print_regR("rcx", regs.rcx); + print_regL("rdx", regs.rdx); + print_regM("rdi", regs.rdi); + print_regR("rsi", regs.rsi); - cons->puts("\n"); - print_regL(" r8", regs.r8); - print_regM(" r9", regs.r9); - print_regR("r10", regs.r10); - print_regL("r11", regs.r11); - print_regM("r12", regs.r12); - print_regR("r13", regs.r13); - print_regL("r14", regs.r14); - print_regM("r15", regs.r15); + cons->puts("\n"); + print_regL(" r8", regs.r8); + print_regM(" r9", regs.r9); + print_regR("r10", regs.r10); + print_regL("r11", regs.r11); + print_regM("r12", regs.r12); + print_regR("r13", regs.r13); + print_regL("r14", regs.r14); + print_regM("r15", regs.r15); - cons->puts("\n\n"); - print_regL("rbp", regs.rbp); - print_regM("rsp", regs.rsp); - print_regR("sp0", cpu.rsp0); + cons->puts("\n\n"); + print_regL("rbp", regs.rbp); + print_regM("rsp", regs.rsp); + print_regR("sp0", cpu.rsp0); - print_regL("rip", regs.rip); - print_regM("cr3", cr3); - print_regR("cr2", cr2); + print_regL("rip", regs.rip); + print_regM("cr3", cr3); + print_regR("cr2", cr2); - cons->puts("\n"); + cons->puts("\n"); } struct frame { - frame *prev; - uintptr_t return_addr; + frame *prev; + uintptr_t return_addr; }; void print_stack(const cpu_state ®s) { - console *cons = console::get(); + console *cons = console::get(); - cons->puts("\nStack:\n"); - uint64_t sp = regs.rsp; - while (sp <= regs.rbp) { - cons->printf("%016x: %016x\n", sp, *reinterpret_cast(sp)); - sp += sizeof(uint64_t); - } + cons->puts("\nStack:\n"); + uint64_t sp = regs.rsp; + while (sp <= regs.rbp) { + cons->printf("%016x: %016x\n", sp, *reinterpret_cast(sp)); + sp += sizeof(uint64_t); + } } diff --git a/src/kernel/debug.h b/src/kernel/debug.h index e7b9e04..424d56c 100644 --- a/src/kernel/debug.h +++ b/src/kernel/debug.h @@ -7,13 +7,13 @@ struct cpu_state; extern "C" { - uintptr_t get_rsp(); - uintptr_t get_rip(); - uintptr_t get_caller(); - uintptr_t get_grandcaller(); - uintptr_t get_frame(int frame); - uintptr_t get_gsbase(); - void _halt(); + uintptr_t get_rsp(); + uintptr_t get_rip(); + uintptr_t get_caller(); + uintptr_t get_grandcaller(); + uintptr_t get_frame(int frame); + uintptr_t get_gsbase(); + void _halt(); } extern size_t __counter_syscall_enter; diff --git a/src/kernel/device_manager.cpp b/src/kernel/device_manager.cpp index 89ea101..48099a3 100644 --- a/src/kernel/device_manager.cpp +++ b/src/kernel/device_manager.cpp @@ -23,417 +23,417 @@ device_manager device_manager::s_instance; struct acpi1_rsdp { - char signature[8]; - uint8_t checksum; - char oem_id[6]; - uint8_t revision; - uint32_t rsdt_address; + char signature[8]; + uint8_t checksum; + char oem_id[6]; + uint8_t revision; + uint32_t rsdt_address; } __attribute__ ((packed)); struct acpi2_rsdp { - char signature[8]; - uint8_t checksum10; - char oem_id[6]; - uint8_t revision; - uint32_t rsdt_address; + char signature[8]; + uint8_t checksum10; + char oem_id[6]; + uint8_t revision; + uint32_t rsdt_address; - uint32_t length; - acpi_table_header *xsdt_address; - uint8_t checksum20; - uint8_t reserved[3]; + uint32_t length; + acpi_table_header *xsdt_address; + uint8_t checksum20; + uint8_t reserved[3]; } __attribute__ ((packed)); bool acpi_table_header::validate(uint32_t expected_type) const { - if (kutil::checksum(this, length) != 0) return false; - return !expected_type || (expected_type == type); + if (kutil::checksum(this, length) != 0) return false; + return !expected_type || (expected_type == type); } device_manager::device_manager() : - m_lapic_base(0) + m_lapic_base(0) { - m_irqs.ensure_capacity(32); - m_irqs.set_size(16); - for (int i = 0; i < 16; ++i) - m_irqs[i] = nullptr; + m_irqs.ensure_capacity(32); + m_irqs.set_size(16); + for (int i = 0; i < 16; ++i) + m_irqs[i] = nullptr; - m_irqs[2] = ignore_endpoint; + m_irqs[2] = ignore_endpoint; } template static const T * check_get_table(const acpi_table_header *header) { - kassert(header && header->validate(T::type_id), "Invalid ACPI table."); - return reinterpret_cast(header); + kassert(header && header->validate(T::type_id), "Invalid ACPI table."); + return reinterpret_cast(header); } void device_manager::parse_acpi(const void *root_table) { - kassert(root_table != 0, "ACPI root table pointer is null."); + kassert(root_table != 0, "ACPI root table pointer is null."); - const acpi1_rsdp *acpi1 = memory::to_virtual( - reinterpret_cast(root_table)); + const acpi1_rsdp *acpi1 = memory::to_virtual( + reinterpret_cast(root_table)); - for (int i = 0; i < sizeof(acpi1->signature); ++i) - kassert(acpi1->signature[i] == expected_signature[i], - "ACPI RSDP table signature mismatch"); + for (int i = 0; i < sizeof(acpi1->signature); ++i) + kassert(acpi1->signature[i] == expected_signature[i], + "ACPI RSDP table signature mismatch"); - uint8_t sum = kutil::checksum(acpi1, sizeof(acpi1_rsdp), 0); - kassert(sum == 0, "ACPI 1.0 RSDP checksum mismatch."); + uint8_t sum = kutil::checksum(acpi1, sizeof(acpi1_rsdp), 0); + kassert(sum == 0, "ACPI 1.0 RSDP checksum mismatch."); - kassert(acpi1->revision > 1, "ACPI 1.0 not supported."); + kassert(acpi1->revision > 1, "ACPI 1.0 not supported."); - const acpi2_rsdp *acpi2 = - reinterpret_cast(acpi1); + const acpi2_rsdp *acpi2 = + reinterpret_cast(acpi1); - sum = kutil::checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp)); - kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch."); + sum = kutil::checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp)); + kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch."); - load_xsdt(memory::to_virtual(acpi2->xsdt_address)); + load_xsdt(memory::to_virtual(acpi2->xsdt_address)); } const device_manager::apic_nmi * device_manager::get_lapic_nmi(uint8_t id) const { - for (const auto &nmi : m_nmis) { - if (nmi.cpu == 0xff || nmi.cpu == id) - return &nmi; - } + for (const auto &nmi : m_nmis) { + if (nmi.cpu == 0xff || nmi.cpu == id) + return &nmi; + } - return nullptr; + return nullptr; } const device_manager::irq_override * device_manager::get_irq_override(uint8_t irq) const { - for (const auto &o : m_overrides) - if (o.source == irq) return &o; + for (const auto &o : m_overrides) + if (o.source == irq) return &o; - return nullptr; + return nullptr; } ioapic * device_manager::get_ioapic(int i) { - return (i < m_ioapics.count()) ? &m_ioapics[i] : nullptr; + return (i < m_ioapics.count()) ? &m_ioapics[i] : nullptr; } static void put_sig(char *into, uint32_t type) { - for (int j=0; j<4; ++j) into[j] = reinterpret_cast(&type)[j]; + for (int j=0; j<4; ++j) into[j] = reinterpret_cast(&type)[j]; } void device_manager::load_xsdt(const acpi_table_header *header) { - const auto *xsdt = check_get_table(header); + const auto *xsdt = check_get_table(header); - char sig[5] = {0,0,0,0,0}; - log::info(logs::device, "ACPI 2.0+ tables loading"); + char sig[5] = {0,0,0,0,0}; + log::info(logs::device, "ACPI 2.0+ tables loading"); - put_sig(sig, xsdt->header.type); - log::debug(logs::device, " Found table %s", sig); + put_sig(sig, xsdt->header.type); + log::debug(logs::device, " Found table %s", sig); - size_t num_tables = acpi_table_entries(xsdt, sizeof(void*)); - for (size_t i = 0; i < num_tables; ++i) { - const acpi_table_header *header = - memory::to_virtual(xsdt->headers[i]); + size_t num_tables = acpi_table_entries(xsdt, sizeof(void*)); + for (size_t i = 0; i < num_tables; ++i) { + const acpi_table_header *header = + memory::to_virtual(xsdt->headers[i]); - put_sig(sig, header->type); - log::debug(logs::device, " Found table %s", sig); + put_sig(sig, header->type); + log::debug(logs::device, " Found table %s", sig); - kassert(header->validate(), "Table failed validation."); + kassert(header->validate(), "Table failed validation."); - switch (header->type) { - case acpi_apic::type_id: - load_apic(header); - break; + switch (header->type) { + case acpi_apic::type_id: + load_apic(header); + break; - case acpi_mcfg::type_id: - load_mcfg(header); - break; + case acpi_mcfg::type_id: + load_mcfg(header); + break; - case acpi_hpet::type_id: - load_hpet(header); - break; + case acpi_hpet::type_id: + load_hpet(header); + break; - default: - break; - } - } + default: + break; + } + } } void device_manager::load_apic(const acpi_table_header *header) { - const auto *apic = check_get_table(header); + const auto *apic = check_get_table(header); - m_lapic_base = apic->local_address; + m_lapic_base = apic->local_address; - size_t count = acpi_table_entries(apic, 1); - uint8_t const *p = apic->controller_data; - uint8_t const *end = p + count; + size_t count = acpi_table_entries(apic, 1); + uint8_t const *p = apic->controller_data; + uint8_t const *end = p + count; - // Pass one: count objcts - unsigned num_lapics = 0; - unsigned num_ioapics = 0; - unsigned num_overrides = 0; - unsigned num_nmis = 0; - while (p < end) { - const uint8_t type = p[0]; - const uint8_t length = p[1]; + // Pass one: count objcts + unsigned num_lapics = 0; + unsigned num_ioapics = 0; + unsigned num_overrides = 0; + unsigned num_nmis = 0; + while (p < end) { + const uint8_t type = p[0]; + const uint8_t length = p[1]; - switch (type) { - case 0: ++num_lapics; break; - case 1: ++num_ioapics; break; - case 2: ++num_overrides; break; - case 4: ++num_nmis; break; - default: break; - } + switch (type) { + case 0: ++num_lapics; break; + case 1: ++num_ioapics; break; + case 2: ++num_overrides; break; + case 4: ++num_nmis; break; + default: break; + } - p += length; - } + p += length; + } - m_apic_ids.set_capacity(num_lapics); - m_ioapics.set_capacity(num_ioapics); - m_overrides.set_capacity(num_overrides); - m_nmis.set_capacity(num_nmis); + m_apic_ids.set_capacity(num_lapics); + m_ioapics.set_capacity(num_ioapics); + m_overrides.set_capacity(num_overrides); + m_nmis.set_capacity(num_nmis); - // Pass two: configure objects - p = apic->controller_data; - while (p < end) { - const uint8_t type = p[0]; - const uint8_t length = p[1]; + // Pass two: configure objects + p = apic->controller_data; + while (p < end) { + const uint8_t type = p[0]; + const uint8_t length = p[1]; - switch (type) { - case 0: { // Local APIC - uint8_t uid = kutil::read_from(p+2); - uint8_t id = kutil::read_from(p+3); - m_apic_ids.append(id); + switch (type) { + case 0: { // Local APIC + uint8_t uid = kutil::read_from(p+2); + uint8_t id = kutil::read_from(p+3); + m_apic_ids.append(id); - log::debug(logs::device, " Local APIC uid %x id %x", uid, id); - } - break; + log::debug(logs::device, " Local APIC uid %x id %x", uid, id); + } + break; - case 1: { // I/O APIC - uintptr_t base = kutil::read_from(p+4); - uint32_t base_gsi = kutil::read_from(p+8); - m_ioapics.emplace(base, base_gsi); + case 1: { // I/O APIC + uintptr_t base = kutil::read_from(p+4); + uint32_t base_gsi = kutil::read_from(p+8); + m_ioapics.emplace(base, base_gsi); - log::debug(logs::device, " IO APIC gsi %x base %x", base_gsi, base); - } - break; + log::debug(logs::device, " IO APIC gsi %x base %x", base_gsi, base); + } + break; - case 2: { // Interrupt source override - irq_override o; - o.source = kutil::read_from(p+3); - o.gsi = kutil::read_from(p+4); - o.flags = kutil::read_from(p+8); - m_overrides.append(o); + case 2: { // Interrupt source override + irq_override o; + o.source = kutil::read_from(p+3); + o.gsi = kutil::read_from(p+4); + o.flags = kutil::read_from(p+8); + m_overrides.append(o); - log::debug(logs::device, " Intr source override IRQ %d -> %d Pol %d Tri %d", - o.source, o.gsi, (o.flags & 0x3), ((o.flags >> 2) & 0x3)); - } - break; + log::debug(logs::device, " Intr source override IRQ %d -> %d Pol %d Tri %d", + o.source, o.gsi, (o.flags & 0x3), ((o.flags >> 2) & 0x3)); + } + break; - case 4: {// LAPIC NMI - apic_nmi nmi; - nmi.cpu = kutil::read_from(p + 2); - nmi.lint = kutil::read_from(p + 5); - nmi.flags = kutil::read_from(p + 3); - m_nmis.append(nmi); + case 4: {// LAPIC NMI + apic_nmi nmi; + nmi.cpu = kutil::read_from(p + 2); + nmi.lint = kutil::read_from(p + 5); + nmi.flags = kutil::read_from(p + 3); + m_nmis.append(nmi); - log::debug(logs::device, " LAPIC NMI Proc %02x LINT%d Pol %d Tri %d", - nmi.cpu, nmi.lint, nmi.flags & 0x3, (nmi.flags >> 2) & 0x3); - } - break; + log::debug(logs::device, " LAPIC NMI Proc %02x LINT%d Pol %d Tri %d", + nmi.cpu, nmi.lint, nmi.flags & 0x3, (nmi.flags >> 2) & 0x3); + } + break; - default: - log::debug(logs::device, " APIC entry type %d", type); - } + default: + log::debug(logs::device, " APIC entry type %d", type); + } - p += length; - } + p += length; + } - m_ioapics[0].mask(3, false); - m_ioapics[0].mask(4, false); + m_ioapics[0].mask(3, false); + m_ioapics[0].mask(4, false); } void device_manager::load_mcfg(const acpi_table_header *header) { - const auto *mcfg = check_get_table(header); + const auto *mcfg = check_get_table(header); - size_t count = acpi_table_entries(mcfg, sizeof(acpi_mcfg_entry)); - m_pci.set_size(count); - m_devices.set_capacity(16); + size_t count = acpi_table_entries(mcfg, sizeof(acpi_mcfg_entry)); + m_pci.set_size(count); + m_devices.set_capacity(16); - for (unsigned i = 0; i < count; ++i) { - const acpi_mcfg_entry &mcfge = mcfg->entries[i]; + for (unsigned i = 0; i < count; ++i) { + const acpi_mcfg_entry &mcfge = mcfg->entries[i]; - m_pci[i].group = mcfge.group; - m_pci[i].bus_start = mcfge.bus_start; - m_pci[i].bus_end = mcfge.bus_end; - m_pci[i].base = memory::to_virtual(mcfge.base); + m_pci[i].group = mcfge.group; + m_pci[i].bus_start = mcfge.bus_start; + m_pci[i].bus_end = mcfge.bus_end; + m_pci[i].base = memory::to_virtual(mcfge.base); - log::debug(logs::device, " Found MCFG entry: base %lx group %d bus %d-%d", - mcfge.base, mcfge.group, mcfge.bus_start, mcfge.bus_end); - } + log::debug(logs::device, " Found MCFG entry: base %lx group %d bus %d-%d", + mcfge.base, mcfge.group, mcfge.bus_start, mcfge.bus_end); + } - probe_pci(); + probe_pci(); } void device_manager::load_hpet(const acpi_table_header *header) { - const auto *hpet = check_get_table(header); + const auto *hpet = check_get_table(header); - log::debug(logs::device, " Found HPET device #%3d: base %016lx pmin %d attr %02x", - hpet->index, hpet->base_address.address, hpet->periodic_min, hpet->attributes); + log::debug(logs::device, " Found HPET device #%3d: base %016lx pmin %d attr %02x", + hpet->index, hpet->base_address.address, hpet->periodic_min, hpet->attributes); - uint32_t hwid = hpet->hardware_id; - uint8_t rev_id = hwid & 0xff; - uint8_t comparators = (hwid >> 8) & 0x1f; - uint8_t count_size_cap = (hwid >> 13) & 1; - uint8_t legacy_replacement = (hwid >> 15) & 1; - uint32_t pci_vendor_id = (hwid >> 16); + uint32_t hwid = hpet->hardware_id; + uint8_t rev_id = hwid & 0xff; + uint8_t comparators = (hwid >> 8) & 0x1f; + uint8_t count_size_cap = (hwid >> 13) & 1; + uint8_t legacy_replacement = (hwid >> 15) & 1; + uint32_t pci_vendor_id = (hwid >> 16); - log::debug(logs::device, " rev:%02d comparators:%02d count_size_cap:%1d legacy_repl:%1d", - rev_id, comparators, count_size_cap, legacy_replacement); - log::debug(logs::device, " pci vendor id: %04x", pci_vendor_id); + log::debug(logs::device, " rev:%02d comparators:%02d count_size_cap:%1d legacy_repl:%1d", + rev_id, comparators, count_size_cap, legacy_replacement); + log::debug(logs::device, " pci vendor id: %04x", pci_vendor_id); - m_hpets.emplace(hpet->index, - reinterpret_cast(hpet->base_address.address + ::memory::page_offset)); + m_hpets.emplace(hpet->index, + reinterpret_cast(hpet->base_address.address + ::memory::page_offset)); } void device_manager::probe_pci() { - for (auto &pci : m_pci) { - log::debug(logs::device, "Probing PCI group at base %016lx", pci.base); + for (auto &pci : m_pci) { + log::debug(logs::device, "Probing PCI group at base %016lx", pci.base); - for (int bus = pci.bus_start; bus <= pci.bus_end; ++bus) { - for (int dev = 0; dev < 32; ++dev) { - if (!pci.has_device(bus, dev, 0)) continue; + for (int bus = pci.bus_start; bus <= pci.bus_end; ++bus) { + for (int dev = 0; dev < 32; ++dev) { + if (!pci.has_device(bus, dev, 0)) continue; - auto &d0 = m_devices.emplace(pci, bus, dev, 0); - if (!d0.multi()) continue; + auto &d0 = m_devices.emplace(pci, bus, dev, 0); + if (!d0.multi()) continue; - for (int i = 1; i < 8; ++i) { - if (pci.has_device(bus, dev, i)) - m_devices.emplace(pci, bus, dev, i); - } - } - } - } + for (int i = 1; i < 8; ++i) { + if (pci.has_device(bus, dev, i)) + m_devices.emplace(pci, bus, dev, i); + } + } + } + } } static uint64_t fake_clock_source(void*) { - static uint64_t value = 0; - return value++; + static uint64_t value = 0; + return value++; } void device_manager::init_drivers() { - // Eventually this should be e.g. a lookup into a loadable driver list - // for now, just look for AHCI devices - /* - for (auto &device : m_devices) { - if (device.devclass() != 1 || device.subclass() != 6) - continue; + // Eventually this should be e.g. a lookup into a loadable driver list + // for now, just look for AHCI devices + /* + for (auto &device : m_devices) { + if (device.devclass() != 1 || device.subclass() != 6) + continue; - if (device.progif() != 1) { - log::warn(logs::device, "Found SATA device %d:%d:%d, but not an AHCI interface.", - device.bus(), device.device(), device.function()); - } + if (device.progif() != 1) { + log::warn(logs::device, "Found SATA device %d:%d:%d, but not an AHCI interface.", + device.bus(), device.device(), device.function()); + } - ahcid.register_device(&device); - } - */ - clock *master_clock = nullptr; - if (m_hpets.count() > 0) { - hpet &h = m_hpets[0]; - h.enable(); + ahcid.register_device(&device); + } + */ + clock *master_clock = nullptr; + if (m_hpets.count() > 0) { + hpet &h = m_hpets[0]; + h.enable(); - // becomes the singleton - master_clock = new clock(h.rate(), hpet_clock_source, &h); - log::info(logs::clock, "Created master clock using HPET 0: Rate %d", h.rate()); - } else { - //TODO: Other clocks, APIC clock? - master_clock = new clock(5000, fake_clock_source, nullptr); - } + // becomes the singleton + master_clock = new clock(h.rate(), hpet_clock_source, &h); + log::info(logs::clock, "Created master clock using HPET 0: Rate %d", h.rate()); + } else { + //TODO: Other clocks, APIC clock? + master_clock = new clock(5000, fake_clock_source, nullptr); + } - kassert(master_clock, "Failed to allocate master clock"); + kassert(master_clock, "Failed to allocate master clock"); } bool device_manager::dispatch_irq(unsigned irq) { - if (irq == 4) { - g_com1.handle_interrupt(); - return true; - } + if (irq == 4) { + g_com1.handle_interrupt(); + return true; + } - if (irq >= m_irqs.count()) - return false; + if (irq >= m_irqs.count()) + return false; - endpoint *e = m_irqs[irq]; - if (!e || e == ignore_endpoint) - return e == ignore_endpoint; + endpoint *e = m_irqs[irq]; + if (!e || e == ignore_endpoint) + return e == ignore_endpoint; - e->signal_irq(irq); - return true; + e->signal_irq(irq); + return true; } bool device_manager::bind_irq(unsigned irq, endpoint *target) { - // TODO: grow if under max size - if (irq >= m_irqs.count()) - return false; + // TODO: grow if under max size + if (irq >= m_irqs.count()) + return false; - m_irqs[irq]= target; - return true; + m_irqs[irq]= target; + return true; } void device_manager::unbind_irqs(endpoint *target) { - const size_t count = m_irqs.count(); - for (size_t i = 0; i < count; ++i) { - if (m_irqs[i] == target) - m_irqs[i] = nullptr; - } + const size_t count = m_irqs.count(); + for (size_t i = 0; i < count; ++i) { + if (m_irqs[i] == target) + m_irqs[i] = nullptr; + } } bool device_manager::allocate_msi(const char *name, pci_device &device, irq_callback cb, void *data) { - /* - // TODO: find gaps to fill - uint8_t irq = m_irqs.count(); - isr vector = isr::irq00 + irq; - m_irqs.append({name, cb, data}); + /* + // TODO: find gaps to fill + uint8_t irq = m_irqs.count(); + isr vector = isr::irq00 + irq; + m_irqs.append({name, cb, data}); - log::debug(logs::device, "Allocating IRQ %02x to %s.", irq, name); + log::debug(logs::device, "Allocating IRQ %02x to %s.", irq, name); - device.write_msi_regs( - 0xFEE00000, - static_cast(vector)); - */ - return true; + device.write_msi_regs( + 0xFEE00000, + static_cast(vector)); + */ + return true; } void device_manager::register_block_device(block_device *blockdev) { - m_blockdevs.append(blockdev); + m_blockdevs.append(blockdev); } diff --git a/src/kernel/device_manager.h b/src/kernel/device_manager.h index 0750bd7..d328e72 100644 --- a/src/kernel/device_manager.h +++ b/src/kernel/device_manager.h @@ -17,154 +17,154 @@ using irq_callback = void (*)(void *); class device_manager { public: - /// Constructor. - device_manager(); + /// Constructor. + device_manager(); - /// Get the system global device manager. - /// \returns A reference to the system device manager - static device_manager & get() { return s_instance; } + /// Get the system global device manager. + /// \returns A reference to the system device manager + static device_manager & get() { return s_instance; } - /// Get an IOAPIC - /// \arg i Index of the requested IOAPIC - /// \returns An object representing the given IOAPIC if it exists, - /// otherwise nullptr. - ioapic * get_ioapic(int i); + /// Get an IOAPIC + /// \arg i Index of the requested IOAPIC + /// \returns An object representing the given IOAPIC if it exists, + /// otherwise nullptr. + ioapic * get_ioapic(int i); - /// Parse ACPI tables. - /// \arg root_table Pointer to the ACPI RSDP - void parse_acpi(const void *root_table); + /// Parse ACPI tables. + /// \arg root_table Pointer to the ACPI RSDP + void parse_acpi(const void *root_table); - /// Intialize drivers for the current device list. - void init_drivers(); + /// Intialize drivers for the current device list. + void init_drivers(); - /// Bind an IRQ to an endpoint - /// \arg irq The IRQ number to bind - /// \arg target The endpoint to recieve messages when the IRQ is signalled - /// \returns True on success - bool bind_irq(unsigned irq, endpoint *target); + /// Bind an IRQ to an endpoint + /// \arg irq The IRQ number to bind + /// \arg target The endpoint to recieve messages when the IRQ is signalled + /// \returns True on success + bool bind_irq(unsigned irq, endpoint *target); - /// Remove IRQ bindings for an endpoint - /// \arg target The endpoint to remove - void unbind_irqs(endpoint *target); + /// Remove IRQ bindings for an endpoint + /// \arg target The endpoint to remove + void unbind_irqs(endpoint *target); - /// Allocate an MSI IRQ for a device - /// \arg name Name of the interrupt, for display to user - /// \arg device Device this MSI is being allocated for - /// \arg cb Callback to call when the interrupt is received - /// \arg data Data to pass to the callback - /// \returns True if an interrupt was allocated successfully - bool allocate_msi( - const char *name, - pci_device &device, - irq_callback cb, - void *data); + /// Allocate an MSI IRQ for a device + /// \arg name Name of the interrupt, for display to user + /// \arg device Device this MSI is being allocated for + /// \arg cb Callback to call when the interrupt is received + /// \arg data Data to pass to the callback + /// \returns True if an interrupt was allocated successfully + bool allocate_msi( + const char *name, + pci_device &device, + irq_callback cb, + void *data); - /// Dispatch an IRQ interrupt - /// \arg irq The irq number of the interrupt - /// \returns True if the interrupt was handled - bool dispatch_irq(unsigned irq); + /// Dispatch an IRQ interrupt + /// \arg irq The irq number of the interrupt + /// \returns True if the interrupt was handled + bool dispatch_irq(unsigned irq); - struct apic_nmi - { - uint8_t cpu; - uint8_t lint; - uint16_t flags; - }; + struct apic_nmi + { + uint8_t cpu; + uint8_t lint; + uint16_t flags; + }; - struct irq_override - { - uint8_t source; - uint16_t flags; - uint32_t gsi; - }; + struct irq_override + { + uint8_t source; + uint16_t flags; + uint32_t gsi; + }; - /// Get the list of APIC ids for other CPUs - inline const kutil::vector & get_apic_ids() const { return m_apic_ids; } + /// Get the list of APIC ids for other CPUs + inline const kutil::vector & get_apic_ids() const { return m_apic_ids; } - /// Get the LAPIC base address - /// \returns The physical base address of the local apic registers - uintptr_t get_lapic_base() const { return m_lapic_base; } + /// Get the LAPIC base address + /// \returns The physical base address of the local apic registers + uintptr_t get_lapic_base() const { return m_lapic_base; } - /// Get the NMI mapping for the given local APIC - /// \arg id ID of the local APIC - /// \returns apic_nmi structure describing the NMI configuration, - /// or null if no configuration was provided - const apic_nmi * get_lapic_nmi(uint8_t id) const; + /// Get the NMI mapping for the given local APIC + /// \arg id ID of the local APIC + /// \returns apic_nmi structure describing the NMI configuration, + /// or null if no configuration was provided + const apic_nmi * get_lapic_nmi(uint8_t id) const; - /// Get the IRQ source override for the given IRQ - /// \arg irq IRQ number (not isr vector) - /// \returns irq_override structure describing that IRQ's - /// configuration, or null if no configuration was provided - const irq_override * get_irq_override(uint8_t irq) const; + /// Get the IRQ source override for the given IRQ + /// \arg irq IRQ number (not isr vector) + /// \returns irq_override structure describing that IRQ's + /// configuration, or null if no configuration was provided + const irq_override * get_irq_override(uint8_t irq) const; - /// Register the existance of a block device. - /// \arg blockdev Pointer to the block device - void register_block_device(block_device *blockdev); + /// Register the existance of a block device. + /// \arg blockdev Pointer to the block device + void register_block_device(block_device *blockdev); - /// Get the number of block devices in the system - /// \returns A count of devices - inline unsigned get_num_block_devices() const { return m_blockdevs.count(); } + /// Get the number of block devices in the system + /// \returns A count of devices + inline unsigned get_num_block_devices() const { return m_blockdevs.count(); } - /// Get a block device - /// \arg i Index of the device to get - /// \returns A pointer to the requested device, or nullptr - inline block_device * get_block_device(unsigned i) - { - return i < m_blockdevs.count() ? - m_blockdevs[i] : nullptr; - } + /// Get a block device + /// \arg i Index of the device to get + /// \returns A pointer to the requested device, or nullptr + inline block_device * get_block_device(unsigned i) + { + return i < m_blockdevs.count() ? + m_blockdevs[i] : nullptr; + } - /// Get an HPET device - /// \arg i Index of the device to get - /// \returns A pointer to the requested device, or nullptr - inline hpet * get_hpet(unsigned i) - { - return i < m_hpets.count() ? - &m_hpets[i] : nullptr; - } + /// Get an HPET device + /// \arg i Index of the device to get + /// \returns A pointer to the requested device, or nullptr + inline hpet * get_hpet(unsigned i) + { + return i < m_hpets.count() ? + &m_hpets[i] : nullptr; + } private: - /// Parse the ACPI XSDT and load relevant sub-tables. - /// \arg xsdt Pointer to the XSDT from the firmware - void load_xsdt(const acpi_table_header *xsdt); + /// Parse the ACPI XSDT and load relevant sub-tables. + /// \arg xsdt Pointer to the XSDT from the firmware + void load_xsdt(const acpi_table_header *xsdt); - /// Parse the ACPI MADT and initialize APICs from it. - /// \arg apic Pointer to the MADT from the XSDT - void load_apic(const acpi_table_header *apic); + /// Parse the ACPI MADT and initialize APICs from it. + /// \arg apic Pointer to the MADT from the XSDT + void load_apic(const acpi_table_header *apic); - /// Parse the ACPI MCFG and initialize PCIe from it. - /// \arg mcfg Pointer to the MCFG from the XSDT - void load_mcfg(const acpi_table_header *mcfg); + /// Parse the ACPI MCFG and initialize PCIe from it. + /// \arg mcfg Pointer to the MCFG from the XSDT + void load_mcfg(const acpi_table_header *mcfg); - /// Parse the ACPI HPET and initialize an HPET from it. - /// \arg hpet Pointer to the HPET from the XSDT - void load_hpet(const acpi_table_header *hpet); + /// Parse the ACPI HPET and initialize an HPET from it. + /// \arg hpet Pointer to the HPET from the XSDT + void load_hpet(const acpi_table_header *hpet); - /// Probe the PCIe busses and add found devices to our - /// device list. The device list is destroyed and rebuilt. - void probe_pci(); + /// Probe the PCIe busses and add found devices to our + /// device list. The device list is destroyed and rebuilt. + void probe_pci(); - /// Handle a bad IRQ. Called when an interrupt is dispatched - /// that has no callback. - void bad_irq(uint8_t irq); + /// Handle a bad IRQ. Called when an interrupt is dispatched + /// that has no callback. + void bad_irq(uint8_t irq); - uintptr_t m_lapic_base; + uintptr_t m_lapic_base; - kutil::vector m_ioapics; - kutil::vector m_hpets; - kutil::vector m_apic_ids; - kutil::vector m_nmis; - kutil::vector m_overrides; + kutil::vector m_ioapics; + kutil::vector m_hpets; + kutil::vector m_apic_ids; + kutil::vector m_nmis; + kutil::vector m_overrides; - kutil::vector m_pci; - kutil::vector m_devices; + kutil::vector m_pci; + kutil::vector m_devices; - kutil::vector m_irqs; + kutil::vector m_irqs; - kutil::vector m_blockdevs; + kutil::vector m_blockdevs; - static device_manager s_instance; + static device_manager s_instance; - device_manager(const device_manager &) = delete; - device_manager operator=(const device_manager &) = delete; + device_manager(const device_manager &) = delete; + device_manager operator=(const device_manager &) = delete; }; diff --git a/src/kernel/frame_allocator.cpp b/src/kernel/frame_allocator.cpp index af10cbf..1d26f98 100644 --- a/src/kernel/frame_allocator.cpp +++ b/src/kernel/frame_allocator.cpp @@ -12,152 +12,152 @@ using memory::frame_size; frame_allocator & frame_allocator::get() { - extern frame_allocator &g_frame_allocator; - return g_frame_allocator; + extern frame_allocator &g_frame_allocator; + return g_frame_allocator; } frame_allocator::frame_allocator(kernel::init::frame_block *frames, size_t count) : - m_blocks {frames}, - m_count {count} + m_blocks {frames}, + m_count {count} { } inline unsigned bsf(uint64_t v) { - asm ("tzcntq %q0, %q1" : "=r"(v) : "0"(v) : "cc"); - return v; + asm ("tzcntq %q0, %q1" : "=r"(v) : "0"(v) : "cc"); + return v; } size_t frame_allocator::allocate(size_t count, uintptr_t *address) { - kutil::scoped_lock lock {m_lock}; + kutil::scoped_lock lock {m_lock}; - for (long i = m_count - 1; i >= 0; --i) { - frame_block &block = m_blocks[i]; + for (long i = m_count - 1; i >= 0; --i) { + frame_block &block = m_blocks[i]; - if (!block.map1) - continue; + if (!block.map1) + continue; - // Tree walk to find the first available page - unsigned o1 = bsf(block.map1); + // Tree walk to find the first available page + unsigned o1 = bsf(block.map1); - uint64_t m2 = block.map2[o1]; - unsigned o2 = bsf(m2); + uint64_t m2 = block.map2[o1]; + unsigned o2 = bsf(m2); - uint64_t m3 = block.bitmap[(o1 << 6) + o2]; - unsigned o3 = bsf(m3); + uint64_t m3 = block.bitmap[(o1 << 6) + o2]; + unsigned o3 = bsf(m3); - unsigned frame = (o1 << 12) + (o2 << 6) + o3; + unsigned frame = (o1 << 12) + (o2 << 6) + o3; - // See how many contiguous pages are here - unsigned n = bsf(~m3 >> o3); - if (n > count) - n = count; + // See how many contiguous pages are here + unsigned n = bsf(~m3 >> o3); + if (n > count) + n = count; - *address = block.base + frame * frame_size; + *address = block.base + frame * frame_size; - // Clear the bits to mark these pages allocated - m3 &= ~(((1 << n) - 1) << o3); - block.bitmap[(o1 << 6) + o2] = m3; - if (!m3) { - // if that was it for this group, clear the next level bit - m2 &= ~(1 << o2); - block.map2[o1] = m2; + // Clear the bits to mark these pages allocated + m3 &= ~(((1 << n) - 1) << o3); + block.bitmap[(o1 << 6) + o2] = m3; + if (!m3) { + // if that was it for this group, clear the next level bit + m2 &= ~(1 << o2); + block.map2[o1] = m2; - if (!m2) { - // if that was cleared too, update the top level - block.map1 &= ~(1 << o1); - } - } + if (!m2) { + // if that was cleared too, update the top level + block.map1 &= ~(1 << o1); + } + } - return n; - } + return n; + } - kassert(false, "frame_allocator ran out of free frames!"); - return 0; + kassert(false, "frame_allocator ran out of free frames!"); + return 0; } void frame_allocator::free(uintptr_t address, size_t count) { - kutil::scoped_lock lock {m_lock}; + kutil::scoped_lock lock {m_lock}; - kassert(address % frame_size == 0, "Trying to free a non page-aligned frame!"); + kassert(address % frame_size == 0, "Trying to free a non page-aligned frame!"); - if (!count) - return; + if (!count) + return; - for (long i = 0; i < m_count; ++i) { - frame_block &block = m_blocks[i]; - uintptr_t end = block.base + block.count * frame_size; + for (long i = 0; i < m_count; ++i) { + frame_block &block = m_blocks[i]; + uintptr_t end = block.base + block.count * frame_size; - if (address < block.base || address >= end) - continue; + if (address < block.base || address >= end) + continue; - uint64_t frame = (address - block.base) >> 12; - unsigned o1 = (frame >> 12) & 0x3f; - unsigned o2 = (frame >> 6) & 0x3f; - unsigned o3 = frame & 0x3f; + uint64_t frame = (address - block.base) >> 12; + unsigned o1 = (frame >> 12) & 0x3f; + unsigned o2 = (frame >> 6) & 0x3f; + unsigned o3 = frame & 0x3f; - while (count--) { - block.map1 |= (1 << o1); - block.map2[o1] |= (1 << o2); - block.bitmap[o2] |= (1 << o3); - if (++o3 == 64) { - o3 = 0; - if (++o2 == 64) { - o2 = 0; - ++o1; - kassert(o1 < 64, "Tried to free pages past the end of a block"); - } - } - } - } + while (count--) { + block.map1 |= (1 << o1); + block.map2[o1] |= (1 << o2); + block.bitmap[o2] |= (1 << o3); + if (++o3 == 64) { + o3 = 0; + if (++o2 == 64) { + o2 = 0; + ++o1; + kassert(o1 < 64, "Tried to free pages past the end of a block"); + } + } + } + } } void frame_allocator::used(uintptr_t address, size_t count) { - kutil::scoped_lock lock {m_lock}; + kutil::scoped_lock lock {m_lock}; - kassert(address % frame_size == 0, "Trying to mark a non page-aligned frame!"); + kassert(address % frame_size == 0, "Trying to mark a non page-aligned frame!"); - if (!count) - return; + if (!count) + return; - for (long i = 0; i < m_count; ++i) { - frame_block &block = m_blocks[i]; - uintptr_t end = block.base + block.count * frame_size; + for (long i = 0; i < m_count; ++i) { + frame_block &block = m_blocks[i]; + uintptr_t end = block.base + block.count * frame_size; - if (address < block.base || address >= end) - continue; + if (address < block.base || address >= end) + continue; - uint64_t frame = (address - block.base) >> 12; - unsigned o1 = (frame >> 12) & 0x3f; - unsigned o2 = (frame >> 6) & 0x3f; - unsigned o3 = frame & 0x3f; + uint64_t frame = (address - block.base) >> 12; + unsigned o1 = (frame >> 12) & 0x3f; + unsigned o2 = (frame >> 6) & 0x3f; + unsigned o3 = frame & 0x3f; - while (count--) { - block.bitmap[o2] &= ~(1 << o3); - if (!block.bitmap[o2]) { - block.map2[o1] &= ~(1 << o2); + while (count--) { + block.bitmap[o2] &= ~(1 << o3); + if (!block.bitmap[o2]) { + block.map2[o1] &= ~(1 << o2); - if (!block.map2[o1]) { - block.map1 &= ~(1 << o1); - } - } + if (!block.map2[o1]) { + block.map1 &= ~(1 << o1); + } + } - if (++o3 == 64) { - o3 = 0; - if (++o2 == 64) { - o2 = 0; - ++o1; - kassert(o1 < 64, "Tried to mark pages past the end of a block"); - } - } - } - } + if (++o3 == 64) { + o3 = 0; + if (++o2 == 64) { + o2 = 0; + ++o1; + kassert(o1 < 64, "Tried to mark pages past the end of a block"); + } + } + } + } } diff --git a/src/kernel/frame_allocator.h b/src/kernel/frame_allocator.h index ac419ca..b0056ce 100644 --- a/src/kernel/frame_allocator.h +++ b/src/kernel/frame_allocator.h @@ -7,47 +7,47 @@ namespace kernel { namespace init { - struct frame_block; + struct frame_block; }} /// Allocator for physical memory frames class frame_allocator { public: - using frame_block = kernel::init::frame_block; + using frame_block = kernel::init::frame_block; - /// Constructor - /// \arg blocks The bootloader-supplied frame bitmap block list - /// \arg count Number of entries in the block list - frame_allocator(frame_block *frames, size_t count); + /// Constructor + /// \arg blocks The bootloader-supplied frame bitmap block list + /// \arg count Number of entries in the block list + frame_allocator(frame_block *frames, size_t count); - /// Get free frames from the free list. Only frames from the first free block - /// are returned, so the number may be less than requested, but they will - /// be contiguous. - /// \arg count The maximum number of frames to get - /// \arg address [out] The physical address of the first frame - /// \returns The number of frames retrieved - size_t allocate(size_t count, uintptr_t *address); + /// Get free frames from the free list. Only frames from the first free block + /// are returned, so the number may be less than requested, but they will + /// be contiguous. + /// \arg count The maximum number of frames to get + /// \arg address [out] The physical address of the first frame + /// \returns The number of frames retrieved + size_t allocate(size_t count, uintptr_t *address); - /// Free previously allocated frames. - /// \arg address The physical address of the first frame to free - /// \arg count The number of frames to be freed - void free(uintptr_t address, size_t count); + /// Free previously allocated frames. + /// \arg address The physical address of the first frame to free + /// \arg count The number of frames to be freed + void free(uintptr_t address, size_t count); - /// Mark frames as used - /// \arg address The physical address of the first frame to free - /// \arg count The number of frames to be freed - void used(uintptr_t address, size_t count); + /// Mark frames as used + /// \arg address The physical address of the first frame to free + /// \arg count The number of frames to be freed + void used(uintptr_t address, size_t count); - /// Get the global frame allocator - static frame_allocator & get(); + /// Get the global frame allocator + static frame_allocator & get(); private: - frame_block *m_blocks; - size_t m_count; + frame_block *m_blocks; + size_t m_count; - kutil::spinlock m_lock; + kutil::spinlock m_lock; - frame_allocator() = delete; - frame_allocator(const frame_allocator &) = delete; + frame_allocator() = delete; + frame_allocator(const frame_allocator &) = delete; }; diff --git a/src/kernel/gdt.cpp b/src/kernel/gdt.cpp index 8f7b8a2..aff2b9a 100644 --- a/src/kernel/gdt.cpp +++ b/src/kernel/gdt.cpp @@ -26,143 +26,143 @@ GDT &g_bsp_gdt = __g_bsp_gdt_storage.value; GDT::GDT(TSS *tss) : - m_tss(tss) + m_tss(tss) { - kutil::memset(this, 0, sizeof(GDT)); + kutil::memset(this, 0, sizeof(GDT)); - m_ptr.limit = sizeof(m_entries) - 1; - m_ptr.base = &m_entries[0]; + m_ptr.limit = sizeof(m_entries) - 1; + m_ptr.base = &m_entries[0]; - // Kernel CS/SS - always 64bit - set(kern_cs_index, 0, 0xfffff, true, type::read_write | type::execute); - set(kern_ss_index, 0, 0xfffff, true, type::read_write); + // Kernel CS/SS - always 64bit + set(kern_cs_index, 0, 0xfffff, true, type::read_write | type::execute); + set(kern_ss_index, 0, 0xfffff, true, type::read_write); - // User CS32/SS/CS64 - layout expected by SYSRET - set(user_cs32_index, 0, 0xfffff, false, type::ring3 | type::read_write | type::execute); - set(user_ss_index, 0, 0xfffff, true, type::ring3 | type::read_write); - set(user_cs64_index, 0, 0xfffff, true, type::ring3 | type::read_write | type::execute); + // User CS32/SS/CS64 - layout expected by SYSRET + set(user_cs32_index, 0, 0xfffff, false, type::ring3 | type::read_write | type::execute); + set(user_ss_index, 0, 0xfffff, true, type::ring3 | type::read_write); + set(user_cs64_index, 0, 0xfffff, true, type::ring3 | type::read_write | type::execute); - set_tss(tss); + set_tss(tss); } GDT & GDT::current() { - cpu_data &cpu = current_cpu(); - return *cpu.gdt; + cpu_data &cpu = current_cpu(); + return *cpu.gdt; } void GDT::install() const { - gdt_write( - static_cast(&m_ptr), - kern_cs_index << 3, - kern_ss_index << 3, - tss_index << 3); + gdt_write( + static_cast(&m_ptr), + kern_cs_index << 3, + kern_ss_index << 3, + tss_index << 3); } void GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t) { - m_entries[i].limit_low = limit & 0xffff; - m_entries[i].size = (limit >> 16) & 0xf; - m_entries[i].size |= (is64 ? 0xa0 : 0xc0); + m_entries[i].limit_low = limit & 0xffff; + m_entries[i].size = (limit >> 16) & 0xf; + m_entries[i].size |= (is64 ? 0xa0 : 0xc0); - m_entries[i].base_low = base & 0xffff; - m_entries[i].base_mid = (base >> 16) & 0xff; - m_entries[i].base_high = (base >> 24) & 0xff; + m_entries[i].base_low = base & 0xffff; + m_entries[i].base_mid = (base >> 16) & 0xff; + m_entries[i].base_high = (base >> 24) & 0xff; - m_entries[i].type = t | type::system | type::present; + m_entries[i].type = t | type::system | type::present; } struct tss_descriptor { - uint16_t limit_low; - uint16_t base_00; - uint8_t base_16; - GDT::type type; - uint8_t size; - uint8_t base_24; - uint32_t base_32; - uint32_t reserved; + uint16_t limit_low; + uint16_t base_00; + uint8_t base_16; + GDT::type type; + uint8_t size; + uint8_t base_24; + uint32_t base_32; + uint32_t reserved; } __attribute__ ((packed)); void GDT::set_tss(TSS *tss) { - tss_descriptor tssd; + tss_descriptor tssd; - size_t limit = sizeof(TSS); - tssd.limit_low = limit & 0xffff; - tssd.size = (limit >> 16) & 0xf; + size_t limit = sizeof(TSS); + tssd.limit_low = limit & 0xffff; + tssd.size = (limit >> 16) & 0xf; - uintptr_t base = reinterpret_cast(tss); - tssd.base_00 = base & 0xffff; - tssd.base_16 = (base >> 16) & 0xff; - tssd.base_24 = (base >> 24) & 0xff; - tssd.base_32 = (base >> 32) & 0xffffffff; - tssd.reserved = 0; + uintptr_t base = reinterpret_cast(tss); + tssd.base_00 = base & 0xffff; + tssd.base_16 = (base >> 16) & 0xff; + tssd.base_24 = (base >> 24) & 0xff; + tssd.base_32 = (base >> 32) & 0xffffffff; + tssd.reserved = 0; - tssd.type = - type::accessed | - type::execute | - type::ring3 | - type::present; + tssd.type = + type::accessed | + type::execute | + type::ring3 | + type::present; - kutil::memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor)); + kutil::memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor)); } void GDT::dump(unsigned index) const { - console *cons = console::get(); + console *cons = console::get(); - unsigned start = 0; - unsigned count = (m_ptr.limit + 1) / sizeof(descriptor); - if (index != -1) { - start = index; - count = 1; - } else { - cons->printf(" GDT: loc:%lx size:%d\n", m_ptr.base, m_ptr.limit+1); - } + unsigned start = 0; + unsigned count = (m_ptr.limit + 1) / sizeof(descriptor); + if (index != -1) { + start = index; + count = 1; + } else { + cons->printf(" GDT: loc:%lx size:%d\n", m_ptr.base, m_ptr.limit+1); + } - const descriptor *gdt = - reinterpret_cast(m_ptr.base); + const descriptor *gdt = + reinterpret_cast(m_ptr.base); - for (int i = start; i < start+count; ++i) { - uint32_t base = - (gdt[i].base_high << 24) | - (gdt[i].base_mid << 16) | - gdt[i].base_low; + for (int i = start; i < start+count; ++i) { + uint32_t base = + (gdt[i].base_high << 24) | + (gdt[i].base_mid << 16) | + gdt[i].base_low; - uint32_t limit = - static_cast(gdt[i].size & 0x0f) << 16 | - gdt[i].limit_low; + uint32_t limit = + static_cast(gdt[i].size & 0x0f) << 16 | + gdt[i].limit_low; - cons->printf(" %02d:", i); - if (! (gdt[i].type && type::present)) { - cons->puts(" Not Present\n"); - continue; - } + cons->printf(" %02d:", i); + if (! (gdt[i].type && type::present)) { + cons->puts(" Not Present\n"); + continue; + } - cons->printf(" Base %08x limit %05x ", base, limit); + cons->printf(" Base %08x limit %05x ", base, limit); - switch (gdt[i].type & type::ring3) { - case type::ring3: cons->puts("ring3"); break; - case type::ring2: cons->puts("ring2"); break; - case type::ring1: cons->puts("ring1"); break; - default: cons->puts("ring0"); break; - } + switch (gdt[i].type & type::ring3) { + case type::ring3: cons->puts("ring3"); break; + case type::ring2: cons->puts("ring2"); break; + case type::ring1: cons->puts("ring1"); break; + default: cons->puts("ring0"); break; + } - cons->printf(" %s %s %s %s %s %s %s\n", - (gdt[i].type && type::accessed) ? "A" : " ", - (gdt[i].type && type::read_write) ? "RW" : " ", - (gdt[i].type && type::conforming) ? "C" : " ", - (gdt[i].type && type::execute) ? "EX" : " ", - (gdt[i].type && type::system) ? "S" : " ", - (gdt[i].size & 0x80) ? "KB" : " B", - (gdt[i].size & 0x60) == 0x20 ? "64" : - (gdt[i].size & 0x60) == 0x40 ? "32" : "16"); - } + cons->printf(" %s %s %s %s %s %s %s\n", + (gdt[i].type && type::accessed) ? "A" : " ", + (gdt[i].type && type::read_write) ? "RW" : " ", + (gdt[i].type && type::conforming) ? "C" : " ", + (gdt[i].type && type::execute) ? "EX" : " ", + (gdt[i].type && type::system) ? "S" : " ", + (gdt[i].size & 0x80) ? "KB" : " B", + (gdt[i].size & 0x60) == 0x20 ? "64" : + (gdt[i].size & 0x60) == 0x40 ? "32" : "16"); + } } diff --git a/src/kernel/gdt.h b/src/kernel/gdt.h index 3651740..e747740 100644 --- a/src/kernel/gdt.h +++ b/src/kernel/gdt.h @@ -10,58 +10,58 @@ class TSS; class GDT { public: - GDT(TSS *tss); + GDT(TSS *tss); - /// Get the currently running CPU's GDT - static GDT & current(); + /// Get the currently running CPU's GDT + static GDT & current(); - /// Install this GDT to the current CPU - void install() const; + /// Install this GDT to the current CPU + void install() const; - /// Get the addrss of the pointer - inline const void * pointer() const { return static_cast(&m_ptr); } + /// Get the addrss of the pointer + inline const void * pointer() const { return static_cast(&m_ptr); } - /// Dump debug information about the GDT to the console. - /// \arg index Which entry to print, or -1 for all entries - void dump(unsigned index = -1) const; + /// Dump debug information about the GDT to the console. + /// \arg index Which entry to print, or -1 for all entries + void dump(unsigned index = -1) const; - enum class type : uint8_t - { - accessed = 0x01, - read_write = 0x02, - conforming = 0x04, - execute = 0x08, - system = 0x10, - ring1 = 0x20, - ring2 = 0x40, - ring3 = 0x60, - present = 0x80 - }; + enum class type : uint8_t + { + accessed = 0x01, + read_write = 0x02, + conforming = 0x04, + execute = 0x08, + system = 0x10, + ring1 = 0x20, + ring2 = 0x40, + ring3 = 0x60, + present = 0x80 + }; private: - void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t); - void set_tss(TSS *tss); + void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t); + void set_tss(TSS *tss); - struct descriptor - { - uint16_t limit_low; - uint16_t base_low; - uint8_t base_mid; - type type; - uint8_t size; - uint8_t base_high; - } __attribute__ ((packed, align(8))); + struct descriptor + { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_mid; + type type; + uint8_t size; + uint8_t base_high; + } __attribute__ ((packed, align(8))); - struct ptr - { - uint16_t limit; - descriptor *base; - } __attribute__ ((packed, align(4))); + struct ptr + { + uint16_t limit; + descriptor *base; + } __attribute__ ((packed, align(4))); - descriptor m_entries[8]; - TSS *m_tss; + descriptor m_entries[8]; + TSS *m_tss; - ptr m_ptr; + ptr m_ptr; }; is_bitfield(GDT::type); diff --git a/src/kernel/hpet.cpp b/src/kernel/hpet.cpp index d554077..99e68a0 100644 --- a/src/kernel/hpet.cpp +++ b/src/kernel/hpet.cpp @@ -6,114 +6,114 @@ #include "log.h" namespace { - inline uint64_t volatile *capabilities(uint64_t volatile *base) { return base; } - inline uint64_t volatile *configuration(uint64_t volatile *base) { return base+2; } - inline uint64_t volatile *interrupt_status(uint64_t volatile *base) { return base+4; } - inline uint64_t volatile *counter_value(uint64_t volatile *base) { return base+30; } + inline uint64_t volatile *capabilities(uint64_t volatile *base) { return base; } + inline uint64_t volatile *configuration(uint64_t volatile *base) { return base+2; } + inline uint64_t volatile *interrupt_status(uint64_t volatile *base) { return base+4; } + inline uint64_t volatile *counter_value(uint64_t volatile *base) { return base+30; } - inline uint64_t volatile *timer_base(uint64_t volatile *base, unsigned i) { return base + 0x20 + (4*i); } - inline uint64_t volatile *timer_config(uint64_t volatile *base, unsigned i) { return timer_base(base, i); } - inline uint64_t volatile *timer_comparator(uint64_t volatile *base, unsigned i) { return timer_base(base, i) + 1; } + inline uint64_t volatile *timer_base(uint64_t volatile *base, unsigned i) { return base + 0x20 + (4*i); } + inline uint64_t volatile *timer_config(uint64_t volatile *base, unsigned i) { return timer_base(base, i); } + inline uint64_t volatile *timer_comparator(uint64_t volatile *base, unsigned i) { return timer_base(base, i) + 1; } } void hpet_irq_callback(void *hpet_ptr) { - if (hpet_ptr) - reinterpret_cast(hpet_ptr)->callback(); + if (hpet_ptr) + reinterpret_cast(hpet_ptr)->callback(); } hpet::hpet(uint8_t index, uint64_t *base) : - m_index(index), - m_base(base) + m_index(index), + m_base(base) { - *configuration(m_base) = 0; - *counter_value(m_base) = 0; + *configuration(m_base) = 0; + *counter_value(m_base) = 0; - uint64_t caps = *capabilities(base); - uint64_t config = *configuration(base); - m_timers = ((caps >> 8) & 0x1f) + 1; - m_period = (caps >> 32); + uint64_t caps = *capabilities(base); + uint64_t config = *configuration(base); + m_timers = ((caps >> 8) & 0x1f) + 1; + m_period = (caps >> 32); - setup_timer_interrupts(0, 2, 1000, true); - // bool installed = device_manager::get() - // .install_irq(2, "HPET Timer", hpet_irq_callback, this); - // kassert(installed, "Installing HPET IRQ handler"); + setup_timer_interrupts(0, 2, 1000, true); + // bool installed = device_manager::get() + // .install_irq(2, "HPET Timer", hpet_irq_callback, this); + // kassert(installed, "Installing HPET IRQ handler"); - log::debug(logs::timer, "HPET %d capabilities:", index); - log::debug(logs::timer, " revision: %d", caps & 0xff); - log::debug(logs::timer, " timers: %d", m_timers); - log::debug(logs::timer, " bits: %d", ((caps >> 13) & 1) ? 64 : 32); - log::debug(logs::timer, " LRR capable: %d", ((caps >> 15) & 1)); - log::debug(logs::timer, " period: %dns", m_period / 1000000); - log::debug(logs::timer, " global enabled: %d", config & 1); - log::debug(logs::timer, " LRR enable: %d", (config >> 1) & 1); + log::debug(logs::timer, "HPET %d capabilities:", index); + log::debug(logs::timer, " revision: %d", caps & 0xff); + log::debug(logs::timer, " timers: %d", m_timers); + log::debug(logs::timer, " bits: %d", ((caps >> 13) & 1) ? 64 : 32); + log::debug(logs::timer, " LRR capable: %d", ((caps >> 15) & 1)); + log::debug(logs::timer, " period: %dns", m_period / 1000000); + log::debug(logs::timer, " global enabled: %d", config & 1); + log::debug(logs::timer, " LRR enable: %d", (config >> 1) & 1); - for (unsigned i = 0; i < m_timers; ++i) { - disable_timer(i); - uint64_t config = *timer_config(m_base, i); + for (unsigned i = 0; i < m_timers; ++i) { + disable_timer(i); + uint64_t config = *timer_config(m_base, i); - log::debug(logs::timer, "HPET %d timer %d:", index, i); - log::debug(logs::timer, " int type: %d", (config >> 1) & 1); - log::debug(logs::timer, " int enable: %d", (config >> 2) & 1); - log::debug(logs::timer, " timer type: %d", (config >> 3) & 1); - log::debug(logs::timer, " periodic cap: %d", (config >> 4) & 1); - log::debug(logs::timer, " bits: %d", ((config >> 5) & 1) ? 64 : 32); - log::debug(logs::timer, " 32 mode: %d", (config >> 8) & 1); - log::debug(logs::timer, " int route: %d", (config >> 9) & 0x1f); - log::debug(logs::timer, " FSB enable: %d", (config >> 14) & 1); - log::debug(logs::timer, " FSB capable: %d", (config >> 15) & 1); - log::debug(logs::timer, " rotung cap: %08x", (config >> 32)); - } + log::debug(logs::timer, "HPET %d timer %d:", index, i); + log::debug(logs::timer, " int type: %d", (config >> 1) & 1); + log::debug(logs::timer, " int enable: %d", (config >> 2) & 1); + log::debug(logs::timer, " timer type: %d", (config >> 3) & 1); + log::debug(logs::timer, " periodic cap: %d", (config >> 4) & 1); + log::debug(logs::timer, " bits: %d", ((config >> 5) & 1) ? 64 : 32); + log::debug(logs::timer, " 32 mode: %d", (config >> 8) & 1); + log::debug(logs::timer, " int route: %d", (config >> 9) & 0x1f); + log::debug(logs::timer, " FSB enable: %d", (config >> 14) & 1); + log::debug(logs::timer, " FSB capable: %d", (config >> 15) & 1); + log::debug(logs::timer, " rotung cap: %08x", (config >> 32)); + } } void hpet::setup_timer_interrupts(unsigned timer, uint8_t irq, uint64_t interval, bool periodic) { - constexpr uint64_t femto_per_us = 1000000000ull; - *timer_comparator(m_base, timer) = - *counter_value(m_base) + - (interval * femto_per_us) / m_period; + constexpr uint64_t femto_per_us = 1000000000ull; + *timer_comparator(m_base, timer) = + *counter_value(m_base) + + (interval * femto_per_us) / m_period; - *timer_config(m_base, timer) = (irq << 9) | ((periodic ? 1 : 0) << 3); + *timer_config(m_base, timer) = (irq << 9) | ((periodic ? 1 : 0) << 3); } void hpet::enable_timer(unsigned timer) { - *timer_config(m_base, timer) = *timer_config(m_base, timer) | (1 << 2); + *timer_config(m_base, timer) = *timer_config(m_base, timer) | (1 << 2); } void hpet::disable_timer(unsigned timer) { - *timer_config(m_base, timer) = *timer_config(m_base, timer) & ~(1ull << 2); + *timer_config(m_base, timer) = *timer_config(m_base, timer) & ~(1ull << 2); } void hpet::callback() { - log::debug(logs::timer, "HPET %d got irq", m_index); + log::debug(logs::timer, "HPET %d got irq", m_index); } void hpet::enable() { - log::debug(logs::timer, "HPET %d enabling", m_index); - *configuration(m_base) = (*configuration(m_base) & 0x3) | 1; + log::debug(logs::timer, "HPET %d enabling", m_index); + *configuration(m_base) = (*configuration(m_base) & 0x3) | 1; } uint64_t hpet::value() const { - return *counter_value(m_base); + return *counter_value(m_base); } uint64_t hpet_clock_source(void *data) { - return reinterpret_cast(data)->value(); + return reinterpret_cast(data)->value(); } diff --git a/src/kernel/hpet.h b/src/kernel/hpet.h index c4f6170..16b0444 100644 --- a/src/kernel/hpet.h +++ b/src/kernel/hpet.h @@ -12,35 +12,35 @@ uint64_t hpet_clock_source(void *); class hpet { public: - /// Constructor. - /// \arg index The index of the HPET out of all HPETs - /// \arg base The base address of the HPET for MMIO - hpet(uint8_t index, uint64_t *base); + /// Constructor. + /// \arg index The index of the HPET out of all HPETs + /// \arg base The base address of the HPET for MMIO + hpet(uint8_t index, uint64_t *base); - /// Configure the timer and start it running. - void enable(); + /// Configure the timer and start it running. + void enable(); - /// Get the timer rate in ticks per us - inline uint64_t rate() const { return 1000000000/m_period; } + /// Get the timer rate in ticks per us + inline uint64_t rate() const { return 1000000000/m_period; } - /// Get the current timer value - uint64_t value() const; + /// Get the current timer value + uint64_t value() const; private: - friend void hpet_irq_callback(void *); - friend uint64_t hpet_clock_source(void *); + friend void hpet_irq_callback(void *); + friend uint64_t hpet_clock_source(void *); - void setup_timer_interrupts(unsigned timer, uint8_t irq, uint64_t interval, bool periodic); - void enable_timer(unsigned timer); - void disable_timer(unsigned timer); + void setup_timer_interrupts(unsigned timer, uint8_t irq, uint64_t interval, bool periodic); + void enable_timer(unsigned timer); + void disable_timer(unsigned timer); - void callback(); + void callback(); - uint8_t m_timers; - uint8_t m_index; + uint8_t m_timers; + uint8_t m_index; - uint64_t m_period; - volatile uint64_t *m_base; + uint64_t m_period; + volatile uint64_t *m_base; }; diff --git a/src/kernel/idt.cpp b/src/kernel/idt.cpp index 92d303c..53c571a 100644 --- a/src/kernel/idt.cpp +++ b/src/kernel/idt.cpp @@ -5,7 +5,7 @@ #include "log.h" extern "C" { - void idt_write(const void *idt_ptr); + void idt_write(const void *idt_ptr); #define ISR(i, s, name) extern void name (); #define NISR(i, s, name) @@ -33,9 +33,9 @@ IDT::set_nmi_handler(uintptr_t address) IDT::IDT() { - kutil::memset(this, 0, sizeof(IDT)); - m_ptr.limit = sizeof(m_entries) - 1; - m_ptr.base = &m_entries[0]; + kutil::memset(this, 0, sizeof(IDT)); + m_ptr.limit = sizeof(m_entries) - 1; + m_ptr.base = &m_entries[0]; #define ISR(i, s, name) set(i, & name, 0x08, 0x8e); #define EISR(i, s, name) set(i, & name, 0x08, 0x8e); @@ -51,14 +51,14 @@ IDT::IDT() IDT & IDT::current() { - cpu_data &cpu = current_cpu(); - return *cpu.idt; + cpu_data &cpu = current_cpu(); + return *cpu.idt; } void IDT::install() const { - idt_write(static_cast(&m_ptr)); + idt_write(static_cast(&m_ptr)); } void @@ -78,7 +78,7 @@ IDT::add_ist_entries() uint8_t IDT::used_ist_entries() const { - constexpr uint8_t entries = + constexpr uint8_t entries = #define ISR(i, s, name) ((s) ? (1 << s) : 0) | #define NISR(i, s, name) ((s) ? (1 << s) : 0) | @@ -92,64 +92,64 @@ IDT::used_ist_entries() const 0; - return entries; + return entries; } void IDT::set(uint8_t i, void (*handler)(), uint16_t selector, uint8_t flags) { - uintptr_t addr = reinterpret_cast(handler); + uintptr_t addr = reinterpret_cast(handler); - m_entries[i].base_low = addr & 0xffff; - m_entries[i].base_mid = (addr >> 16) & 0xffff; - m_entries[i].base_high = (addr >> 32) & 0xffffffff; - m_entries[i].selector = selector; - m_entries[i].flags = flags; - m_entries[i].ist = 0; - m_entries[i].reserved = 0; + m_entries[i].base_low = addr & 0xffff; + m_entries[i].base_mid = (addr >> 16) & 0xffff; + m_entries[i].base_high = (addr >> 32) & 0xffffffff; + m_entries[i].selector = selector; + m_entries[i].flags = flags; + m_entries[i].ist = 0; + m_entries[i].reserved = 0; } void IDT::dump(unsigned index) const { - unsigned start = 0; - unsigned count = (m_ptr.limit + 1) / sizeof(descriptor); - if (index != -1) { - start = index; - count = 1; - log::info(logs::boot, "IDT FOR INDEX %02x", index); - } else { - log::info(logs::boot, "Loaded IDT at: %lx size: %d bytes", m_ptr.base, m_ptr.limit+1); - } + unsigned start = 0; + unsigned count = (m_ptr.limit + 1) / sizeof(descriptor); + if (index != -1) { + start = index; + count = 1; + log::info(logs::boot, "IDT FOR INDEX %02x", index); + } else { + log::info(logs::boot, "Loaded IDT at: %lx size: %d bytes", m_ptr.base, m_ptr.limit+1); + } - const descriptor *idt = - reinterpret_cast(m_ptr.base); + const descriptor *idt = + reinterpret_cast(m_ptr.base); - for (int i = start; i < start+count; ++i) { - uint64_t base = - (static_cast(idt[i].base_high) << 32) | - (static_cast(idt[i].base_mid) << 16) | - idt[i].base_low; + for (int i = start; i < start+count; ++i) { + uint64_t base = + (static_cast(idt[i].base_high) << 32) | + (static_cast(idt[i].base_mid) << 16) | + idt[i].base_low; - char const *type; - switch (idt[i].flags & 0xf) { - case 0x5: type = " 32tsk "; break; - case 0x6: type = " 16int "; break; - case 0x7: type = " 16trp "; break; - case 0xe: type = " 32int "; break; - case 0xf: type = " 32trp "; break; - default: type = " ????? "; break; - } + char const *type; + switch (idt[i].flags & 0xf) { + case 0x5: type = " 32tsk "; break; + case 0x6: type = " 16int "; break; + case 0x7: type = " 16trp "; break; + case 0xe: type = " 32int "; break; + case 0xf: type = " 32trp "; break; + default: type = " ????? "; break; + } - if (idt[i].flags & 0x80) { - log::debug(logs::boot, - " Entry %3d: Base:%lx Sel(rpl %d, ti %d, %3d) IST:%d %s DPL:%d", i, base, - (idt[i].selector & 0x3), - ((idt[i].selector & 0x4) >> 2), - (idt[i].selector >> 3), - idt[i].ist, - type, - ((idt[i].flags >> 5) & 0x3)); - } - } + if (idt[i].flags & 0x80) { + log::debug(logs::boot, + " Entry %3d: Base:%lx Sel(rpl %d, ti %d, %3d) IST:%d %s DPL:%d", i, base, + (idt[i].selector & 0x3), + ((idt[i].selector & 0x4) >> 2), + (idt[i].selector >> 3), + idt[i].ist, + type, + ((idt[i].flags >> 5) & 0x3)); + } + } } diff --git a/src/kernel/idt.h b/src/kernel/idt.h index fb74a7d..a0ccce2 100644 --- a/src/kernel/idt.h +++ b/src/kernel/idt.h @@ -6,62 +6,62 @@ class IDT { public: - IDT(); + IDT(); - /// Get the currently running CPU's IDT - static IDT & current(); + /// Get the currently running CPU's IDT + static IDT & current(); /// Set the global NMI handler. Must happen before creating /// any IDTs. static void set_nmi_handler(uintptr_t address); - /// Install this IDT to the current CPU - void install() const; + /// Install this IDT to the current CPU + void install() const; - /// Add the IST entries listed in the ISR table into the IDT. - /// This can't be done until after memory is set up so the - /// stacks can be created. - void add_ist_entries(); + /// Add the IST entries listed in the ISR table into the IDT. + /// This can't be done until after memory is set up so the + /// stacks can be created. + void add_ist_entries(); - /// Get the IST entry used by an entry. - /// \arg i Which IDT entry to look in - /// \returns The IST index used by entry i, or 0 for none - inline uint8_t get_ist(uint8_t i) const { - return m_entries[i].ist; - } + /// Get the IST entry used by an entry. + /// \arg i Which IDT entry to look in + /// \returns The IST index used by entry i, or 0 for none + inline uint8_t get_ist(uint8_t i) const { + return m_entries[i].ist; + } - /// Set the IST entry used by an entry. - /// \arg i Which IDT entry to set - /// \arg ist The IST index for entry i, or 0 for none - void set_ist(uint8_t i, uint8_t ist) { m_entries[i].ist = ist; } + /// Set the IST entry used by an entry. + /// \arg i Which IDT entry to set + /// \arg ist The IST index for entry i, or 0 for none + void set_ist(uint8_t i, uint8_t ist) { m_entries[i].ist = ist; } - /// Get the IST entries that are used by this table, as a bitmap - uint8_t used_ist_entries() const; + /// Get the IST entries that are used by this table, as a bitmap + uint8_t used_ist_entries() const; - /// Dump debug information about the IDT to the console. - /// \arg index Which entry to print, or -1 for all entries - void dump(unsigned index = -1) const; + /// Dump debug information about the IDT to the console. + /// \arg index Which entry to print, or -1 for all entries + void dump(unsigned index = -1) const; private: - void set(uint8_t i, void (*handler)(), uint16_t selector, uint8_t flags); + void set(uint8_t i, void (*handler)(), uint16_t selector, uint8_t flags); - struct descriptor - { - uint16_t base_low; - uint16_t selector; - uint8_t ist; - uint8_t flags; - uint16_t base_mid; - uint32_t base_high; - uint32_t reserved; // must be zero - } __attribute__ ((packed, aligned(16))); + struct descriptor + { + uint16_t base_low; + uint16_t selector; + uint8_t ist; + uint8_t flags; + uint16_t base_mid; + uint32_t base_high; + uint32_t reserved; // must be zero + } __attribute__ ((packed, aligned(16))); - struct ptr - { - uint16_t limit; - descriptor *base; - } __attribute__ ((packed, aligned(4))); + struct ptr + { + uint16_t limit; + descriptor *base; + } __attribute__ ((packed, aligned(4))); - descriptor m_entries[256]; - ptr m_ptr; + descriptor m_entries[256]; + ptr m_ptr; }; diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index 0ee2e7b..ccc2903 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -18,14 +18,14 @@ static const uint16_t PIC2 = 0xa0; constexpr uintptr_t apic_eoi_addr = 0xfee000b0 + ::memory::page_offset; extern "C" { - void isr_handler(cpu_state*); - void irq_handler(cpu_state*); + void isr_handler(cpu_state*); + void irq_handler(cpu_state*); } uint8_t get_irq(unsigned vector) { - switch (vector) { + switch (vector) { #define ISR(i, s, name) #define EISR(i, s, name) #define NISR(i, s, name) @@ -36,51 +36,51 @@ get_irq(unsigned vector) #undef EISR #undef ISR - default: return 0xff; - } + default: return 0xff; + } } void disable_legacy_pic() { - // Mask all interrupts - outb(PIC2+1, 0xfc); - outb(PIC1+1, 0xff); + // Mask all interrupts + outb(PIC2+1, 0xfc); + outb(PIC1+1, 0xff); - // Start initialization sequence - outb(PIC1, 0x11); io_wait(); - outb(PIC2, 0x11); io_wait(); + // Start initialization sequence + outb(PIC1, 0x11); io_wait(); + outb(PIC2, 0x11); io_wait(); - // Remap into ignore ISRs - outb(PIC1+1, static_cast(isr::isrIgnore0)); io_wait(); - outb(PIC2+1, static_cast(isr::isrIgnore8)); io_wait(); + // Remap into ignore ISRs + outb(PIC1+1, static_cast(isr::isrIgnore0)); io_wait(); + outb(PIC2+1, static_cast(isr::isrIgnore8)); io_wait(); - // Tell PICs about each other - outb(PIC1+1, 0x04); io_wait(); - outb(PIC2+1, 0x02); io_wait(); + // Tell PICs about each other + outb(PIC1+1, 0x04); io_wait(); + outb(PIC2+1, 0x02); io_wait(); } void isr_handler(cpu_state *regs) { - uint8_t vector = regs->interrupt & 0xff; + uint8_t vector = regs->interrupt & 0xff; if ((vector & 0xf0) == 0xf0) { *reinterpret_cast(apic_eoi_addr) = 0; return; } - // Clear out the IST for this vector so we just keep using - // this stack - IDT &idt = IDT::current(); - uint8_t old_ist = idt.get_ist(vector); - if (old_ist) - idt.set_ist(vector, 0); + // Clear out the IST for this vector so we just keep using + // this stack + IDT &idt = IDT::current(); + uint8_t old_ist = idt.get_ist(vector); + if (old_ist) + idt.set_ist(vector, 0); char message[200]; - switch (static_cast(vector)) { + switch (static_cast(vector)) { - case isr::isrDebug: + case isr::isrDebug: asm volatile ("mov %%dr0, %%r8" ::: "r8"); asm volatile ("mov %%dr1, %%r9" ::: "r9"); asm volatile ("mov %%dr2, %%r10" ::: "r10"); @@ -90,15 +90,15 @@ isr_handler(cpu_state *regs) asm volatile ("mov %%dr6, %%r14" ::: "r14"); asm volatile ("mov %%dr7, %%r15" ::: "r15"); kassert(false, "Debug exception"); - break; + break; - case isr::isrDoubleFault: + case isr::isrDoubleFault: kassert(false, "Double fault"); - break; + break; - case isr::isrGPFault: + case isr::isrGPFault: if (regs->errorcode & 0xfff0) { - int index = (regs->errorcode & 0xffff) >> 4; + int index = (regs->errorcode & 0xffff) >> 4; int ti = (regs->errorcode & 0x07) >> 1; char const *table = (ti & 1) ? "IDT" : @@ -114,20 +114,20 @@ isr_handler(cpu_state *regs) kassert(false, message); break; - case isr::isrPageFault: { - uintptr_t cr2 = 0; - __asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2)); + case isr::isrPageFault: { + uintptr_t cr2 = 0; + __asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2)); - bool user = cr2 < memory::kernel_offset; - vm_space::fault_type ft = - static_cast(regs->errorcode); + bool user = cr2 < memory::kernel_offset; + vm_space::fault_type ft = + static_cast(regs->errorcode); - vm_space &space = user - ? process::current().space() - : vm_space::kernel_space(); + vm_space &space = user + ? process::current().space() + : vm_space::kernel_space(); - if (cr2 && space.handle_fault(cr2, ft)) - break; + if (cr2 && space.handle_fault(cr2, ft)) + break; snprintf(message, sizeof(message), "Page fault: %016llx%s%s%s%s%s", cr2, @@ -137,42 +137,42 @@ isr_handler(cpu_state *regs) (regs->errorcode & 0x08) ? " reserved" : "", (regs->errorcode & 0x10) ? " ip" : ""); kassert(false, message); - } - break; + } + break; - case isr::isrTimer: - scheduler::get().schedule(); - break; + case isr::isrTimer: + scheduler::get().schedule(); + break; - case isr::isrLINT0: - case isr::isrLINT1: - break; + case isr::isrLINT0: + case isr::isrLINT1: + break; - case isr::isrSpurious: - // No EOI for the spurious interrupt - return; + case isr::isrSpurious: + // No EOI for the spurious interrupt + return; - default: + default: snprintf(message, sizeof(message), "Unknown interrupt 0x%x", regs->interrupt); kassert(false, message); - } + } - // Return the IST for this vector to what it was - if (old_ist) - idt.set_ist(vector, old_ist); - *reinterpret_cast(apic_eoi_addr) = 0; + // Return the IST for this vector to what it was + if (old_ist) + idt.set_ist(vector, old_ist); + *reinterpret_cast(apic_eoi_addr) = 0; } void irq_handler(cpu_state *regs) { - uint8_t irq = get_irq(regs->interrupt); - if (! device_manager::get().dispatch_irq(irq)) { + uint8_t irq = get_irq(regs->interrupt); + if (! device_manager::get().dispatch_irq(irq)) { char message[100]; snprintf(message, sizeof(message), "Unknown IRQ: %d (vec 0x%x)", irq, regs->interrupt); kassert(false, message); - } + } - *reinterpret_cast(apic_eoi_addr) = 0; + *reinterpret_cast(apic_eoi_addr) = 0; } diff --git a/src/kernel/interrupts.h b/src/kernel/interrupts.h index b325edd..6789008 100644 --- a/src/kernel/interrupts.h +++ b/src/kernel/interrupts.h @@ -17,7 +17,7 @@ enum class isr : uint8_t #undef NISR #undef ISR - _zero = 0 + _zero = 0 }; /// Helper operator to add an offset to an isr vector @@ -26,11 +26,11 @@ constexpr isr operator+(const isr &lhs, int rhs) { } extern "C" { - /// Set the CPU interrupt enable flag (sti) - void interrupts_enable(); + /// Set the CPU interrupt enable flag (sti) + void interrupts_enable(); - /// Set the CPU interrupt disable flag (cli) - void interrupts_disable(); + /// Set the CPU interrupt disable flag (cli) + void interrupts_disable(); } /// Disable the legacy PIC diff --git a/src/kernel/io.cpp b/src/kernel/io.cpp index c9ed88f..f5aa618 100644 --- a/src/kernel/io.cpp +++ b/src/kernel/io.cpp @@ -3,20 +3,20 @@ uint8_t inb(uint16_t port) { - uint8_t val; - __asm__ __volatile__ ( "inb %1, %0" : "=a"(val) : "Nd"(port) ); - return val; + uint8_t val; + __asm__ __volatile__ ( "inb %1, %0" : "=a"(val) : "Nd"(port) ); + return val; } void outb(uint16_t port, uint8_t val) { - __asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) ); + __asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) ); } void io_wait(unsigned times) { - for (unsigned i = 0; i < times; ++i) - outb(0x80, 0); + for (unsigned i = 0; i < times; ++i) + outb(0x80, 0); } diff --git a/src/kernel/log.cpp b/src/kernel/log.cpp index 3d1ff9c..8e48f8c 100644 --- a/src/kernel/log.cpp +++ b/src/kernel/log.cpp @@ -19,73 +19,73 @@ static const uint8_t level_colors[] = {0x07, 0x07, 0x0f, 0x0b, 0x09}; static void output_log(log::area_t area, log::level severity, const char *message) { - auto *cons = console::get(); - cons->set_color(level_colors[static_cast(severity)]); - cons->printf("%7s %5s: %s\n", - g_logger.area_name(area), - g_logger.level_name(severity), - message); - cons->set_color(); + auto *cons = console::get(); + cons->set_color(level_colors[static_cast(severity)]); + cons->printf("%7s %5s: %s\n", + g_logger.area_name(area), + g_logger.level_name(severity), + message); + cons->set_color(); } static void log_flush() { - system &sys = system::get(); - sys.assert_signal(j6_signal_system_has_log); + system &sys = system::get(); + sys.assert_signal(j6_signal_system_has_log); } void logger_task() { - auto *cons = console::get(); + auto *cons = console::get(); - log::info(logs::task, "Starting kernel logger task"); - g_logger.set_immediate(nullptr); - g_logger.set_flush(log_flush); + log::info(logs::task, "Starting kernel logger task"); + g_logger.set_immediate(nullptr); + g_logger.set_flush(log_flush); - thread &self = thread::current(); - system &sys = system::get(); + thread &self = thread::current(); + system &sys = system::get(); - size_t buffer_size = 1; - uint8_t *buffer = nullptr; + size_t buffer_size = 1; + uint8_t *buffer = nullptr; - while (true) { - size_t size = g_logger.get_entry(buffer, buffer_size); - if (size > buffer_size) { - while (size > buffer_size) buffer_size *= 2; - kutil::kfree(buffer); - buffer = reinterpret_cast(kutil::kalloc(buffer_size)); - kassert(buffer, "Could not allocate logger task buffer"); - continue; - } + while (true) { + size_t size = g_logger.get_entry(buffer, buffer_size); + if (size > buffer_size) { + while (size > buffer_size) buffer_size *= 2; + kutil::kfree(buffer); + buffer = reinterpret_cast(kutil::kalloc(buffer_size)); + kassert(buffer, "Could not allocate logger task buffer"); + continue; + } - if(size) { - auto *ent = reinterpret_cast(buffer); - buffer[ent->bytes] = 0; + if(size) { + auto *ent = reinterpret_cast(buffer); + buffer[ent->bytes] = 0; - cons->set_color(level_colors[static_cast(ent->severity)]); - cons->printf("%7s %5s: %s\n", - g_logger.area_name(ent->area), - g_logger.level_name(ent->severity), - ent->message); - cons->set_color(); - } + cons->set_color(level_colors[static_cast(ent->severity)]); + cons->printf("%7s %5s: %s\n", + g_logger.area_name(ent->area), + g_logger.level_name(ent->severity), + ent->message); + cons->set_color(); + } - if (!g_logger.has_log()) { - sys.deassert_signal(j6_signal_system_has_log); - sys.add_blocked_thread(&self); - self.wait_on_signals(j6_signal_system_has_log); - } - } + if (!g_logger.has_log()) { + sys.deassert_signal(j6_signal_system_has_log); + sys.add_blocked_thread(&self); + self.wait_on_signals(j6_signal_system_has_log); + } + } } void logger_init() { - new (&g_logger) log::logger(log_buffer, sizeof(log_buffer), output_log); + new (&g_logger) log::logger(log_buffer, sizeof(log_buffer), output_log); } void logger_clear_immediate() { - g_logger.set_immediate(nullptr); + g_logger.set_immediate(nullptr); } diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 2e0c291..38d33f0 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -33,13 +33,13 @@ #endif extern "C" { - void kernel_main(kernel::init::args *args); - void (*__ctors)(void); - void (*__ctors_end)(void); - void long_ap_startup(cpu_data *cpu); - void ap_startup(); - void ap_idle(); - void init_ap_trampoline(void*, cpu_data *, void (*)()); + void kernel_main(kernel::init::args *args); + void (*__ctors)(void); + void (*__ctors_end)(void); + void long_ap_startup(cpu_data *cpu); + void ap_startup(); + void ap_idle(); + void init_ap_trampoline(void*, cpu_data *, void (*)()); } using namespace kernel; @@ -57,23 +57,23 @@ unsigned start_aps(lapic &apic, const kutil::vector &ids, void *kpml4); void init_console() { - serial_port *com1 = new (&g_com1) serial_port(COM1); - console *cons = new (&g_console) console(com1); + serial_port *com1 = new (&g_com1) serial_port(COM1); + console *cons = new (&g_console) console(com1); - cons->set_color(0x21, 0x00); - cons->puts("jsix OS "); - cons->set_color(0x08, 0x00); - cons->puts(GIT_VERSION " booting...\n"); + cons->set_color(0x21, 0x00); + cons->puts("jsix OS "); + cons->set_color(0x08, 0x00); + cons->puts(GIT_VERSION " booting...\n"); } void run_constructors() { - void (**p)(void) = &__ctors; - while (p < &__ctors_end) { - void (*ctor)(void) = *p++; - if (ctor) ctor(); - } + void (**p)(void) = &__ctors; + while (p < &__ctors_end) { + void (*ctor)(void) = *p++; + if (ctor) ctor(); + } } void @@ -84,230 +84,230 @@ kernel_main(init::args *args) kutil::assert::symbol_table = args->symbol_table | memory::page_offset; } - init_console(); - logger_init(); + init_console(); + logger_init(); - cpu_validate(); + cpu_validate(); - kassert(args->magic == init::args_magic, + kassert(args->magic == init::args_magic, "Bad kernel args magic number"); - log::debug(logs::boot, "jsix init args are at: %016lx", args); - log::debug(logs::boot, " Memory map is at: %016lx", args->mem_map); - log::debug(logs::boot, "ACPI root table is at: %016lx", args->acpi_table); - log::debug(logs::boot, "Runtime service is at: %016lx", args->runtime_services); - log::debug(logs::boot, " Kernel PML4 is at: %016lx", args->pml4); + log::debug(logs::boot, "jsix init args are at: %016lx", args); + log::debug(logs::boot, " Memory map is at: %016lx", args->mem_map); + log::debug(logs::boot, "ACPI root table is at: %016lx", args->acpi_table); + log::debug(logs::boot, "Runtime service is at: %016lx", args->runtime_services); + log::debug(logs::boot, " Kernel PML4 is at: %016lx", args->pml4); - uint64_t cr0, cr4; - asm ("mov %%cr0, %0" : "=r"(cr0)); - asm ("mov %%cr4, %0" : "=r"(cr4)); - uint64_t efer = rdmsr(msr::ia32_efer); - log::debug(logs::boot, "Control regs: cr0:%lx cr4:%lx efer:%lx", cr0, cr4, efer); + uint64_t cr0, cr4; + asm ("mov %%cr0, %0" : "=r"(cr0)); + asm ("mov %%cr4, %0" : "=r"(cr4)); + uint64_t efer = rdmsr(msr::ia32_efer); + log::debug(logs::boot, "Control regs: cr0:%lx cr4:%lx efer:%lx", cr0, cr4, efer); - extern IDT &g_bsp_idt; - extern TSS &g_bsp_tss; - extern GDT &g_bsp_gdt; - extern cpu_data g_bsp_cpu_data; - extern uintptr_t idle_stack_end; + extern IDT &g_bsp_idt; + extern TSS &g_bsp_tss; + extern GDT &g_bsp_gdt; + extern cpu_data g_bsp_cpu_data; + extern uintptr_t idle_stack_end; - cpu_data *cpu = &g_bsp_cpu_data; - kutil::memset(cpu, 0, sizeof(cpu_data)); + cpu_data *cpu = &g_bsp_cpu_data; + kutil::memset(cpu, 0, sizeof(cpu_data)); - cpu->self = cpu; - cpu->idt = new (&g_bsp_idt) IDT; - cpu->tss = new (&g_bsp_tss) TSS; - cpu->gdt = new (&g_bsp_gdt) GDT {cpu->tss}; - cpu->rsp0 = idle_stack_end; - cpu_early_init(cpu); + cpu->self = cpu; + cpu->idt = new (&g_bsp_idt) IDT; + cpu->tss = new (&g_bsp_tss) TSS; + cpu->gdt = new (&g_bsp_gdt) GDT {cpu->tss}; + cpu->rsp0 = idle_stack_end; + cpu_early_init(cpu); - disable_legacy_pic(); + disable_legacy_pic(); - memory_initialize_pre_ctors(*args); - run_constructors(); - memory_initialize_post_ctors(*args); + memory_initialize_pre_ctors(*args); + run_constructors(); + memory_initialize_post_ctors(*args); - cpu->tss->create_ist_stacks(cpu->idt->used_ist_entries()); + cpu->tss->create_ist_stacks(cpu->idt->used_ist_entries()); - syscall_initialize(); + syscall_initialize(); - device_manager &devices = device_manager::get(); - devices.parse_acpi(args->acpi_table); + device_manager &devices = device_manager::get(); + devices.parse_acpi(args->acpi_table); - // Need the local APIC to get the BSP's id - uintptr_t apic_base = devices.get_lapic_base(); + // Need the local APIC to get the BSP's id + uintptr_t apic_base = devices.get_lapic_base(); - lapic *apic = new lapic(apic_base); - apic->enable(); + lapic *apic = new lapic(apic_base); + apic->enable(); - cpu->id = apic->get_id(); - cpu->apic = apic; + cpu->id = apic->get_id(); + cpu->apic = apic; - cpu_init(cpu, true); + cpu_init(cpu, true); - devices.init_drivers(); - apic->calibrate_timer(); + devices.init_drivers(); + apic->calibrate_timer(); - const auto &apic_ids = devices.get_apic_ids(); - unsigned num_cpus = start_aps(*apic, apic_ids, args->pml4); + const auto &apic_ids = devices.get_apic_ids(); + unsigned num_cpus = start_aps(*apic, apic_ids, args->pml4); - interrupts_enable(); - g_com1.handle_interrupt(); + interrupts_enable(); + g_com1.handle_interrupt(); - /* - block_device *disk = devices->get_block_device(0); - if (disk) { - for (int i=0; i<1; ++i) { - uint8_t buf[512]; - kutil::memset(buf, 0, 512); + /* + block_device *disk = devices->get_block_device(0); + if (disk) { + for (int i=0; i<1; ++i) { + uint8_t buf[512]; + kutil::memset(buf, 0, 512); - kassert(disk->read(0x200, sizeof(buf), buf), - "Disk read returned 0"); + kassert(disk->read(0x200, sizeof(buf), buf), + "Disk read returned 0"); - console *cons = console::get(); - uint8_t *p = &buf[0]; - for (int i = 0; i < 8; ++i) { - for (int j = 0; j < 16; ++j) { - cons->printf(" %02x", *p++); - } - cons->putc('\n'); - } - } - } else { - log::warn(logs::boot, "No block devices present."); - } - */ + console *cons = console::get(); + uint8_t *p = &buf[0]; + for (int i = 0; i < 8; ++i) { + for (int j = 0; j < 16; ++j) { + cons->printf(" %02x", *p++); + } + cons->putc('\n'); + } + } + } else { + log::warn(logs::boot, "No block devices present."); + } + */ - scheduler *sched = new scheduler {num_cpus}; - scheduler_ready = true; + scheduler *sched = new scheduler {num_cpus}; + scheduler_ready = true; - // Load the init server - load_init_server(*args->init, args->modules); + // Load the init server + load_init_server(*args->init, args->modules); - sched->create_kernel_task(logger_task, scheduler::max_priority/2, true); - sched->start(); + sched->create_kernel_task(logger_task, scheduler::max_priority/2, true); + sched->start(); } unsigned start_aps(lapic &apic, const kutil::vector &ids, void *kpml4) { - using memory::frame_size; - using memory::kernel_stack_pages; + using memory::frame_size; + using memory::kernel_stack_pages; - extern size_t ap_startup_code_size; - extern process &g_kernel_process; - extern vm_area_guarded &g_kernel_stacks; + extern size_t ap_startup_code_size; + extern process &g_kernel_process; + extern vm_area_guarded &g_kernel_stacks; - clock &clk = clock::get(); + clock &clk = clock::get(); - ap_startup_count = 1; // BSP processor - log::info(logs::boot, "Starting %d other CPUs", ids.count() - 1); + ap_startup_count = 1; // BSP processor + log::info(logs::boot, "Starting %d other CPUs", ids.count() - 1); - // Since we're using address space outside kernel space, make sure - // the kernel's vm_space is used - cpu_data &bsp = current_cpu(); - bsp.process = &g_kernel_process; + // Since we're using address space outside kernel space, make sure + // the kernel's vm_space is used + cpu_data &bsp = current_cpu(); + bsp.process = &g_kernel_process; - uint16_t index = bsp.index; + uint16_t index = bsp.index; - // Copy the startup code somwhere the real mode trampoline can run - uintptr_t addr = 0x8000; // TODO: find a valid address, rewrite addresses - uint8_t vector = addr >> 12; - vm_area *vma = new vm_area_fixed(addr, 0x1000, vm_flags::write); - vm_space::kernel_space().add(addr, vma); - kutil::memcpy( - reinterpret_cast(addr), - reinterpret_cast(&ap_startup), - ap_startup_code_size); + // Copy the startup code somwhere the real mode trampoline can run + uintptr_t addr = 0x8000; // TODO: find a valid address, rewrite addresses + uint8_t vector = addr >> 12; + vm_area *vma = new vm_area_fixed(addr, 0x1000, vm_flags::write); + vm_space::kernel_space().add(addr, vma); + kutil::memcpy( + reinterpret_cast(addr), + reinterpret_cast(&ap_startup), + ap_startup_code_size); - // AP idle stacks need less room than normal stacks, so pack multiple - // into a normal stack area - static constexpr size_t idle_stack_bytes = 2048; // 2KiB is generous - static constexpr size_t full_stack_bytes = kernel_stack_pages * frame_size; - static constexpr size_t idle_stacks_per = full_stack_bytes / idle_stack_bytes; + // AP idle stacks need less room than normal stacks, so pack multiple + // into a normal stack area + static constexpr size_t idle_stack_bytes = 2048; // 2KiB is generous + static constexpr size_t full_stack_bytes = kernel_stack_pages * frame_size; + static constexpr size_t idle_stacks_per = full_stack_bytes / idle_stack_bytes; - uint8_t ist_entries = IDT::current().used_ist_entries(); + uint8_t ist_entries = IDT::current().used_ist_entries(); - size_t free_stack_count = 0; - uintptr_t stack_area_start = 0; + size_t free_stack_count = 0; + uintptr_t stack_area_start = 0; - lapic::ipi mode = lapic::ipi::init | lapic::ipi::level | lapic::ipi::assert; - apic.send_ipi_broadcast(mode, false, 0); + lapic::ipi mode = lapic::ipi::init | lapic::ipi::level | lapic::ipi::assert; + apic.send_ipi_broadcast(mode, false, 0); - for (uint8_t id : ids) { - if (id == bsp.id) continue; + for (uint8_t id : ids) { + if (id == bsp.id) continue; - // Set up the CPU data structures - IDT *idt = new IDT; - TSS *tss = new TSS; - GDT *gdt = new GDT {tss}; - cpu_data *cpu = new cpu_data; - kutil::memset(cpu, 0, sizeof(cpu_data)); + // Set up the CPU data structures + IDT *idt = new IDT; + TSS *tss = new TSS; + GDT *gdt = new GDT {tss}; + cpu_data *cpu = new cpu_data; + kutil::memset(cpu, 0, sizeof(cpu_data)); - cpu->self = cpu; - cpu->id = id; - cpu->index = ++index; - cpu->idt = idt; - cpu->tss = tss; - cpu->gdt = gdt; + cpu->self = cpu; + cpu->id = id; + cpu->index = ++index; + cpu->idt = idt; + cpu->tss = tss; + cpu->gdt = gdt; - tss->create_ist_stacks(ist_entries); + tss->create_ist_stacks(ist_entries); - // Set up the CPU's idle task stack - if (free_stack_count == 0) { - stack_area_start = g_kernel_stacks.get_section(); - free_stack_count = idle_stacks_per; - } + // Set up the CPU's idle task stack + if (free_stack_count == 0) { + stack_area_start = g_kernel_stacks.get_section(); + free_stack_count = idle_stacks_per; + } - uintptr_t stack_end = stack_area_start + free_stack_count-- * idle_stack_bytes; - stack_end -= 2 * sizeof(void*); // Null frame - *reinterpret_cast(stack_end) = 0; // pre-fault the page - cpu->rsp0 = stack_end; + uintptr_t stack_end = stack_area_start + free_stack_count-- * idle_stack_bytes; + stack_end -= 2 * sizeof(void*); // Null frame + *reinterpret_cast(stack_end) = 0; // pre-fault the page + cpu->rsp0 = stack_end; - // Set up the trampoline with this CPU's data - init_ap_trampoline(kpml4, cpu, ap_idle); + // Set up the trampoline with this CPU's data + init_ap_trampoline(kpml4, cpu, ap_idle); - // Kick it off! - size_t current_count = ap_startup_count; - log::debug(logs::boot, "Starting AP %d: stack %llx", cpu->index, stack_end); + // Kick it off! + size_t current_count = ap_startup_count; + log::debug(logs::boot, "Starting AP %d: stack %llx", cpu->index, stack_end); - lapic::ipi startup = lapic::ipi::startup | lapic::ipi::assert; + lapic::ipi startup = lapic::ipi::startup | lapic::ipi::assert; - apic.send_ipi(startup, vector, id); - for (unsigned i = 0; i < 20; ++i) { - if (ap_startup_count > current_count) break; - clk.spinwait(20); - } + apic.send_ipi(startup, vector, id); + for (unsigned i = 0; i < 20; ++i) { + if (ap_startup_count > current_count) break; + clk.spinwait(20); + } - // If the CPU already incremented ap_startup_count, it's done - if (ap_startup_count > current_count) - continue; + // If the CPU already incremented ap_startup_count, it's done + if (ap_startup_count > current_count) + continue; - // Send the second SIPI (intel recommends this) - apic.send_ipi(startup, vector, id); - for (unsigned i = 0; i < 100; ++i) { - if (ap_startup_count > current_count) break; - clk.spinwait(100); - } + // Send the second SIPI (intel recommends this) + apic.send_ipi(startup, vector, id); + for (unsigned i = 0; i < 100; ++i) { + if (ap_startup_count > current_count) break; + clk.spinwait(100); + } - log::warn(logs::boot, "No response from AP %d within timeout", id); - } + log::warn(logs::boot, "No response from AP %d within timeout", id); + } - log::info(logs::boot, "%d CPUs running", ap_startup_count); - vm_space::kernel_space().remove(vma); - return ap_startup_count; + log::info(logs::boot, "%d CPUs running", ap_startup_count); + vm_space::kernel_space().remove(vma); + return ap_startup_count; } void long_ap_startup(cpu_data *cpu) { - cpu_init(cpu, false); - ++ap_startup_count; - while (!scheduler_ready) asm ("pause"); + cpu_init(cpu, false); + ++ap_startup_count; + while (!scheduler_ready) asm ("pause"); - uintptr_t apic_base = - device_manager::get().get_lapic_base(); - cpu->apic = new lapic(apic_base); - cpu->apic->enable(); + uintptr_t apic_base = + device_manager::get().get_lapic_base(); + cpu->apic = new lapic(apic_base); + cpu->apic->enable(); - scheduler::get().start(); + scheduler::get().start(); } diff --git a/src/kernel/memory_bootstrap.cpp b/src/kernel/memory_bootstrap.cpp index 2a00909..078910f 100644 --- a/src/kernel/memory_bootstrap.cpp +++ b/src/kernel/memory_bootstrap.cpp @@ -52,10 +52,10 @@ static kutil::no_construct __g_kernel_stacks_storage; vm_area_guarded &g_kernel_stacks = __g_kernel_stacks_storage.value; vm_area_guarded g_kernel_buffers { - memory::buffers_start, - memory::kernel_buffer_pages, - memory::kernel_max_buffers, - vm_flags::write}; + memory::buffers_start, + memory::kernel_buffer_pages, + memory::kernel_max_buffers, + vm_flags::write}; void * operator new(size_t size) { return g_kernel_heap.allocate(size); } void * operator new [] (size_t size) { return g_kernel_heap.allocate(size); } @@ -63,149 +63,149 @@ void operator delete (void *p) noexcept { return g_kernel_heap.free(p); } void operator delete [] (void *p) noexcept { return g_kernel_heap.free(p); } namespace kutil { - void * kalloc(size_t size) { return g_kernel_heap.allocate(size); } - void kfree(void *p) { return g_kernel_heap.free(p); } + void * kalloc(size_t size) { return g_kernel_heap.allocate(size); } + void kfree(void *p) { return g_kernel_heap.free(p); } } template uintptr_t get_physical_page(T *p) { - return memory::page_align_down(reinterpret_cast(p)); + return memory::page_align_down(reinterpret_cast(p)); } void memory_initialize_pre_ctors(init::args &kargs) { - using kernel::init::frame_block; + using kernel::init::frame_block; - page_table *kpml4 = static_cast(kargs.pml4); + page_table *kpml4 = static_cast(kargs.pml4); - new (&g_kernel_heap) kutil::heap_allocator {heap_start, kernel_max_heap}; + new (&g_kernel_heap) kutil::heap_allocator {heap_start, kernel_max_heap}; - frame_block *blocks = reinterpret_cast(memory::bitmap_start); - new (&g_frame_allocator) frame_allocator {blocks, kargs.frame_blocks.count}; + frame_block *blocks = reinterpret_cast(memory::bitmap_start); + new (&g_frame_allocator) frame_allocator {blocks, kargs.frame_blocks.count}; - // Mark all the things the bootloader allocated for us as used - allocation_register *reg = kargs.allocations; - while (reg) { - for (auto &alloc : reg->entries) - if (alloc.type != init::allocation_type::none) - g_frame_allocator.used(alloc.address, alloc.count); - reg = reg->next; - } + // Mark all the things the bootloader allocated for us as used + allocation_register *reg = kargs.allocations; + while (reg) { + for (auto &alloc : reg->entries) + if (alloc.type != init::allocation_type::none) + g_frame_allocator.used(alloc.address, alloc.count); + reg = reg->next; + } - process *kp = process::create_kernel_process(kpml4); - vm_space &vm = kp->space(); + process *kp = process::create_kernel_process(kpml4); + vm_space &vm = kp->space(); - vm_area *heap = new (&g_kernel_heap_area) - vm_area_untracked(kernel_max_heap, vm_flags::write); + vm_area *heap = new (&g_kernel_heap_area) + vm_area_untracked(kernel_max_heap, vm_flags::write); - vm.add(heap_start, heap); + vm.add(heap_start, heap); - vm_area *stacks = new (&g_kernel_stacks) vm_area_guarded { - memory::stacks_start, - memory::kernel_stack_pages, - memory::kernel_max_stacks, - vm_flags::write}; - vm.add(memory::stacks_start, &g_kernel_stacks); + vm_area *stacks = new (&g_kernel_stacks) vm_area_guarded { + memory::stacks_start, + memory::kernel_stack_pages, + memory::kernel_max_stacks, + vm_flags::write}; + vm.add(memory::stacks_start, &g_kernel_stacks); - // Clean out any remaning bootloader page table entries - for (unsigned i = 0; i < memory::pml4e_kernel; ++i) - kpml4->entries[i] = 0; + // Clean out any remaning bootloader page table entries + for (unsigned i = 0; i < memory::pml4e_kernel; ++i) + kpml4->entries[i] = 0; } void memory_initialize_post_ctors(init::args &kargs) { - vm_space &vm = vm_space::kernel_space(); - vm.add(memory::buffers_start, &g_kernel_buffers); + vm_space &vm = vm_space::kernel_space(); + vm.add(memory::buffers_start, &g_kernel_buffers); - g_frame_allocator.free( - get_physical_page(kargs.page_tables.pointer), - kargs.page_tables.count); + g_frame_allocator.free( + get_physical_page(kargs.page_tables.pointer), + kargs.page_tables.count); } static void log_mtrrs() { - uint64_t mtrrcap = rdmsr(msr::ia32_mtrrcap); - uint64_t mtrrdeftype = rdmsr(msr::ia32_mtrrdeftype); - unsigned vcap = mtrrcap & 0xff; - log::debug(logs::boot, "MTRRs: vcap=%d %s %s def=%02x %s %s", - vcap, - (mtrrcap & (1<< 8)) ? "fix" : "", - (mtrrcap & (1<<10)) ? "wc" : "", - mtrrdeftype & 0xff, - (mtrrdeftype & (1<<10)) ? "fe" : "", - (mtrrdeftype & (1<<11)) ? "enabled" : "" - ); + uint64_t mtrrcap = rdmsr(msr::ia32_mtrrcap); + uint64_t mtrrdeftype = rdmsr(msr::ia32_mtrrdeftype); + unsigned vcap = mtrrcap & 0xff; + log::debug(logs::boot, "MTRRs: vcap=%d %s %s def=%02x %s %s", + vcap, + (mtrrcap & (1<< 8)) ? "fix" : "", + (mtrrcap & (1<<10)) ? "wc" : "", + mtrrdeftype & 0xff, + (mtrrdeftype & (1<<10)) ? "fe" : "", + (mtrrdeftype & (1<<11)) ? "enabled" : "" + ); - for (unsigned i = 0; i < vcap; ++i) { - uint64_t base = rdmsr(find_mtrr(msr::ia32_mtrrphysbase, i)); - uint64_t mask = rdmsr(find_mtrr(msr::ia32_mtrrphysmask, i)); - log::debug(logs::boot, " vcap[%2d] base:%016llx mask:%016llx type:%02x %s", i, - (base & ~0xfffull), - (mask & ~0xfffull), - (base & 0xff), - (mask & (1<<11)) ? "valid" : ""); - } + for (unsigned i = 0; i < vcap; ++i) { + uint64_t base = rdmsr(find_mtrr(msr::ia32_mtrrphysbase, i)); + uint64_t mask = rdmsr(find_mtrr(msr::ia32_mtrrphysmask, i)); + log::debug(logs::boot, " vcap[%2d] base:%016llx mask:%016llx type:%02x %s", i, + (base & ~0xfffull), + (mask & ~0xfffull), + (base & 0xff), + (mask & (1<<11)) ? "valid" : ""); + } - msr mtrr_fixed[] = { - msr::ia32_mtrrfix64k_00000, - msr::ia32_mtrrfix16k_80000, - msr::ia32_mtrrfix16k_a0000, - msr::ia32_mtrrfix4k_c0000, - msr::ia32_mtrrfix4k_c8000, - msr::ia32_mtrrfix4k_d0000, - msr::ia32_mtrrfix4k_d8000, - msr::ia32_mtrrfix4k_e0000, - msr::ia32_mtrrfix4k_e8000, - msr::ia32_mtrrfix4k_f0000, - msr::ia32_mtrrfix4k_f8000, - }; + msr mtrr_fixed[] = { + msr::ia32_mtrrfix64k_00000, + msr::ia32_mtrrfix16k_80000, + msr::ia32_mtrrfix16k_a0000, + msr::ia32_mtrrfix4k_c0000, + msr::ia32_mtrrfix4k_c8000, + msr::ia32_mtrrfix4k_d0000, + msr::ia32_mtrrfix4k_d8000, + msr::ia32_mtrrfix4k_e0000, + msr::ia32_mtrrfix4k_e8000, + msr::ia32_mtrrfix4k_f0000, + msr::ia32_mtrrfix4k_f8000, + }; - for (int i = 0; i < 11; ++i) { - uint64_t v = rdmsr(mtrr_fixed[i]); - log::debug(logs::boot, " fixed[%2d] %02x %02x %02x %02x %02x %02x %02x %02x", i, - ((v << 0) & 0xff), ((v << 8) & 0xff), ((v << 16) & 0xff), ((v << 24) & 0xff), - ((v << 32) & 0xff), ((v << 40) & 0xff), ((v << 48) & 0xff), ((v << 56) & 0xff)); - } + for (int i = 0; i < 11; ++i) { + uint64_t v = rdmsr(mtrr_fixed[i]); + log::debug(logs::boot, " fixed[%2d] %02x %02x %02x %02x %02x %02x %02x %02x", i, + ((v << 0) & 0xff), ((v << 8) & 0xff), ((v << 16) & 0xff), ((v << 24) & 0xff), + ((v << 32) & 0xff), ((v << 40) & 0xff), ((v << 48) & 0xff), ((v << 56) & 0xff)); + } - uint64_t pat = rdmsr(msr::ia32_pat); - static const char *pat_names[] = {"UC ","WC ","XX ","XX ","WT ","WP ","WB ","UC-"}; - log::debug(logs::boot, " PAT: 0:%s 1:%s 2:%s 3:%s 4:%s 5:%s 6:%s 7:%s", - pat_names[(pat >> (0*8)) & 7], pat_names[(pat >> (1*8)) & 7], - pat_names[(pat >> (2*8)) & 7], pat_names[(pat >> (3*8)) & 7], - pat_names[(pat >> (4*8)) & 7], pat_names[(pat >> (5*8)) & 7], - pat_names[(pat >> (6*8)) & 7], pat_names[(pat >> (7*8)) & 7]); + uint64_t pat = rdmsr(msr::ia32_pat); + static const char *pat_names[] = {"UC ","WC ","XX ","XX ","WT ","WP ","WB ","UC-"}; + log::debug(logs::boot, " PAT: 0:%s 1:%s 2:%s 3:%s 4:%s 5:%s 6:%s 7:%s", + pat_names[(pat >> (0*8)) & 7], pat_names[(pat >> (1*8)) & 7], + pat_names[(pat >> (2*8)) & 7], pat_names[(pat >> (3*8)) & 7], + pat_names[(pat >> (4*8)) & 7], pat_names[(pat >> (5*8)) & 7], + pat_names[(pat >> (6*8)) & 7], pat_names[(pat >> (7*8)) & 7]); } void load_init_server(init::program &program, uintptr_t modules_address) { - process *p = new process; - p->add_handle(&system::get()); + process *p = new process; + p->add_handle(&system::get()); - vm_space &space = p->space(); - for (const auto § : program.sections) { - vm_flags flags = - ((sect.type && section_flags::execute) ? vm_flags::exec : vm_flags::none) | - ((sect.type && section_flags::write) ? vm_flags::write : vm_flags::none); + vm_space &space = p->space(); + for (const auto § : program.sections) { + vm_flags flags = + ((sect.type && section_flags::execute) ? vm_flags::exec : vm_flags::none) | + ((sect.type && section_flags::write) ? vm_flags::write : vm_flags::none); - vm_area *vma = new vm_area_fixed(sect.phys_addr, sect.size, flags); - space.add(sect.virt_addr, vma); - } + vm_area *vma = new vm_area_fixed(sect.phys_addr, sect.size, flags); + space.add(sect.virt_addr, vma); + } - uint64_t iopl = (3ull << 12); + uint64_t iopl = (3ull << 12); - thread *main = p->create_thread(); - main->add_thunk_user(program.entrypoint, 0, iopl); - main->set_state(thread::state::ready); + thread *main = p->create_thread(); + main->add_thunk_user(program.entrypoint, 0, iopl); + main->set_state(thread::state::ready); - // Hacky: No process exists to have created a stack for init; it needs to create - // its own stack. We take advantage of that to use rsp to pass it the init modules - // address. - auto *tcb = main->tcb(); - tcb->rsp3 = modules_address; + // Hacky: No process exists to have created a stack for init; it needs to create + // its own stack. We take advantage of that to use rsp to pass it the init modules + // address. + auto *tcb = main->tcb(); + tcb->rsp3 = modules_address; } diff --git a/src/kernel/msr.cpp b/src/kernel/msr.cpp index 4efb175..ae57def 100644 --- a/src/kernel/msr.cpp +++ b/src/kernel/msr.cpp @@ -3,22 +3,22 @@ msr find_mtrr(msr type, unsigned index) { - return static_cast(static_cast(type) + (2 * index)); + return static_cast(static_cast(type) + (2 * index)); } uint64_t rdmsr(msr addr) { - uint32_t low, high; - __asm__ __volatile__ ("rdmsr" : "=a"(low), "=d"(high) : "c"(addr)); - return (static_cast(high) << 32) | low; + uint32_t low, high; + __asm__ __volatile__ ("rdmsr" : "=a"(low), "=d"(high) : "c"(addr)); + return (static_cast(high) << 32) | low; } void wrmsr(msr addr, uint64_t value) { - uint32_t low = value & 0xffffffff; - uint32_t high = value >> 32; - __asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high)); + uint32_t low = value & 0xffffffff; + uint32_t high = value >> 32; + __asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high)); } diff --git a/src/kernel/msr.h b/src/kernel/msr.h index ee02d45..1ed7a1c 100644 --- a/src/kernel/msr.h +++ b/src/kernel/msr.h @@ -6,34 +6,34 @@ enum class msr : uint32_t { - ia32_mtrrcap = 0x000000fe, - ia32_mtrrdeftype = 0x000002ff, + ia32_mtrrcap = 0x000000fe, + ia32_mtrrdeftype = 0x000002ff, - ia32_mtrrphysbase = 0x00000200, - ia32_mtrrphysmask = 0x00000201, + ia32_mtrrphysbase = 0x00000200, + ia32_mtrrphysmask = 0x00000201, - ia32_mtrrfix64k_00000 = 0x00000250, + ia32_mtrrfix64k_00000 = 0x00000250, - ia32_mtrrfix16k_80000 = 0x00000258, - ia32_mtrrfix16k_a0000 = 0x00000259, + ia32_mtrrfix16k_80000 = 0x00000258, + ia32_mtrrfix16k_a0000 = 0x00000259, - ia32_mtrrfix4k_c0000 = 0x00000268, - ia32_mtrrfix4k_c8000 = 0x00000269, - ia32_mtrrfix4k_d0000 = 0x0000026A, - ia32_mtrrfix4k_d8000 = 0x0000026B, - ia32_mtrrfix4k_e0000 = 0x0000026C, - ia32_mtrrfix4k_e8000 = 0x0000026D, - ia32_mtrrfix4k_f0000 = 0x0000026E, - ia32_mtrrfix4k_f8000 = 0x0000026F, + ia32_mtrrfix4k_c0000 = 0x00000268, + ia32_mtrrfix4k_c8000 = 0x00000269, + ia32_mtrrfix4k_d0000 = 0x0000026A, + ia32_mtrrfix4k_d8000 = 0x0000026B, + ia32_mtrrfix4k_e0000 = 0x0000026C, + ia32_mtrrfix4k_e8000 = 0x0000026D, + ia32_mtrrfix4k_f0000 = 0x0000026E, + ia32_mtrrfix4k_f8000 = 0x0000026F, - ia32_pat = 0x00000277, - ia32_efer = 0xc0000080, - ia32_star = 0xc0000081, - ia32_lstar = 0xc0000082, - ia32_fmask = 0xc0000084, + ia32_pat = 0x00000277, + ia32_efer = 0xc0000080, + ia32_star = 0xc0000081, + ia32_lstar = 0xc0000082, + ia32_fmask = 0xc0000084, - ia32_gs_base = 0xc0000101, - ia32_kernel_gs_base = 0xc0000102 + ia32_gs_base = 0xc0000101, + ia32_kernel_gs_base = 0xc0000102 }; /// Find the msr for MTRR physical base or mask diff --git a/src/kernel/objects/channel.cpp b/src/kernel/objects/channel.cpp index 47f2806..c1db0d4 100644 --- a/src/kernel/objects/channel.cpp +++ b/src/kernel/objects/channel.cpp @@ -9,82 +9,82 @@ extern vm_area_guarded g_kernel_buffers; constexpr size_t buffer_bytes = memory::kernel_buffer_pages * memory::frame_size; channel::channel() : - m_len(0), - m_data(g_kernel_buffers.get_section()), - m_buffer(reinterpret_cast(m_data), buffer_bytes), - kobject(kobject::type::channel, j6_signal_channel_can_send) + m_len(0), + m_data(g_kernel_buffers.get_section()), + m_buffer(reinterpret_cast(m_data), buffer_bytes), + kobject(kobject::type::channel, j6_signal_channel_can_send) { } channel::~channel() { - if (!closed()) close(); + if (!closed()) close(); } j6_status_t channel::enqueue(size_t *len, const void *data) { - // TODO: Make this thread safe! - if (closed()) - return j6_status_closed; + // TODO: Make this thread safe! + if (closed()) + return j6_status_closed; - if (!len || !*len) - return j6_err_invalid_arg; + if (!len || !*len) + return j6_err_invalid_arg; - if (m_buffer.free_space() == 0) - return j6_err_not_ready; + if (m_buffer.free_space() == 0) + return j6_err_not_ready; - void *buffer = nullptr; - size_t avail = m_buffer.reserve(*len, &buffer); - *len = *len > avail ? avail : *len; + void *buffer = nullptr; + size_t avail = m_buffer.reserve(*len, &buffer); + *len = *len > avail ? avail : *len; - kutil::memcpy(buffer, data, *len); - m_buffer.commit(*len); + kutil::memcpy(buffer, data, *len); + m_buffer.commit(*len); - assert_signal(j6_signal_channel_can_recv); - if (m_buffer.free_space() == 0) - deassert_signal(j6_signal_channel_can_send); + assert_signal(j6_signal_channel_can_recv); + if (m_buffer.free_space() == 0) + deassert_signal(j6_signal_channel_can_send); - return j6_status_ok; + return j6_status_ok; } j6_status_t channel::dequeue(size_t *len, void *data) { - // TODO: Make this thread safe! - if (closed()) - return j6_status_closed; + // TODO: Make this thread safe! + if (closed()) + return j6_status_closed; - if (!len || !*len) - return j6_err_invalid_arg; + if (!len || !*len) + return j6_err_invalid_arg; - if (m_buffer.size() == 0) - return j6_err_not_ready; + if (m_buffer.size() == 0) + return j6_err_not_ready; - void *buffer = nullptr; - size_t avail = m_buffer.get_block(&buffer); - *len = *len > avail ? avail : *len; + void *buffer = nullptr; + size_t avail = m_buffer.get_block(&buffer); + *len = *len > avail ? avail : *len; - kutil::memcpy(data, buffer, *len); - m_buffer.consume(*len); + kutil::memcpy(data, buffer, *len); + m_buffer.consume(*len); - assert_signal(j6_signal_channel_can_send); - if (m_buffer.size() == 0) - deassert_signal(j6_signal_channel_can_recv); + assert_signal(j6_signal_channel_can_send); + if (m_buffer.size() == 0) + deassert_signal(j6_signal_channel_can_recv); - return j6_status_ok; + return j6_status_ok; } void channel::close() { - kobject::close(); - g_kernel_buffers.return_section(m_data); + kobject::close(); + g_kernel_buffers.return_section(m_data); } void channel::on_no_handles() { - kobject::on_no_handles(); - delete this; + kobject::on_no_handles(); + delete this; } diff --git a/src/kernel/objects/channel.h b/src/kernel/objects/channel.h index 5ce949f..40cb7b0 100644 --- a/src/kernel/objects/channel.h +++ b/src/kernel/objects/channel.h @@ -8,42 +8,42 @@ /// Channels are bi-directional means of sending messages class channel : - public kobject + public kobject { public: - channel(); - virtual ~channel(); + channel(); + virtual ~channel(); - static constexpr kobject::type type = kobject::type::channel; + static constexpr kobject::type type = kobject::type::channel; - /// Check if the channel has space for a message to be sent - inline bool can_send() const { return check_signal(j6_signal_channel_can_send); } + /// Check if the channel has space for a message to be sent + inline bool can_send() const { return check_signal(j6_signal_channel_can_send); } - /// Check if the channel has a message wiating already - inline bool can_receive() const { return check_signal(j6_signal_channel_can_recv); } + /// Check if the channel has a message wiating already + inline bool can_receive() const { return check_signal(j6_signal_channel_can_recv); } - /// Put a message into the channel - /// \arg len [in] Bytes in data buffer [out] number of bytes written - /// \arg data Pointer to the message data - /// \returns j6_status_ok on success - j6_status_t enqueue(size_t *len, const void *data); + /// Put a message into the channel + /// \arg len [in] Bytes in data buffer [out] number of bytes written + /// \arg data Pointer to the message data + /// \returns j6_status_ok on success + j6_status_t enqueue(size_t *len, const void *data); - /// Get a message from the channel, copied into a provided buffer - /// \arg len On input, the size of the provided buffer. On output, - /// the size of the message copied into the buffer. - /// \arg data Pointer to the buffer - /// \returns j6_status_ok on success - j6_status_t dequeue(size_t *len, void *data); + /// Get a message from the channel, copied into a provided buffer + /// \arg len On input, the size of the provided buffer. On output, + /// the size of the message copied into the buffer. + /// \arg data Pointer to the buffer + /// \returns j6_status_ok on success + j6_status_t dequeue(size_t *len, void *data); - /// Mark this channel as closed, all future calls to enqueue or - /// dequeue messages will fail with j6_status_closed. - virtual void close() override; + /// Mark this channel as closed, all future calls to enqueue or + /// dequeue messages will fail with j6_status_closed. + virtual void close() override; protected: - virtual void on_no_handles() override; + virtual void on_no_handles() override; private: - size_t m_len; - uintptr_t m_data; - kutil::bip_buffer m_buffer; + size_t m_len; + uintptr_t m_data; + kutil::bip_buffer m_buffer; }; diff --git a/src/kernel/objects/endpoint.cpp b/src/kernel/objects/endpoint.cpp index bb232a9..6b6a9ef 100644 --- a/src/kernel/objects/endpoint.cpp +++ b/src/kernel/objects/endpoint.cpp @@ -5,128 +5,128 @@ #include "vm_space.h" endpoint::endpoint() : - kobject {kobject::type::endpoint} + kobject {kobject::type::endpoint} {} endpoint::~endpoint() { - if (!check_signal(j6_signal_closed)) - close(); + if (!check_signal(j6_signal_closed)) + close(); } void endpoint::close() { - kobject::close(); + kobject::close(); - for (auto &data : m_blocked) { - if (data.th) - data.th->wake_on_result(this, j6_status_closed); - } + for (auto &data : m_blocked) { + if (data.th) + data.th->wake_on_result(this, j6_status_closed); + } - device_manager::get().unbind_irqs(this); + device_manager::get().unbind_irqs(this); } j6_status_t endpoint::send(j6_tag_t tag, size_t len, void *data) { - thread_data sender = { &thread::current(), data }; - sender.len = len; - sender.tag = tag; + thread_data sender = { &thread::current(), data }; + sender.len = len; + sender.tag = tag; - if (!check_signal(j6_signal_endpoint_can_send)) { - assert_signal(j6_signal_endpoint_can_recv); - m_blocked.append(sender); - sender.th->wait_on_object(this); + if (!check_signal(j6_signal_endpoint_can_send)) { + assert_signal(j6_signal_endpoint_can_recv); + m_blocked.append(sender); + sender.th->wait_on_object(this); - // we woke up having already finished the send - // because it happened in the receiver - return sender.th->get_wait_result(); - } + // we woke up having already finished the send + // because it happened in the receiver + return sender.th->get_wait_result(); + } - thread_data receiver = m_blocked.pop_front(); - if (m_blocked.count() == 0) - deassert_signal(j6_signal_endpoint_can_send); + thread_data receiver = m_blocked.pop_front(); + if (m_blocked.count() == 0) + deassert_signal(j6_signal_endpoint_can_send); - j6_status_t status = do_message_copy(sender, receiver); + j6_status_t status = do_message_copy(sender, receiver); - receiver.th->wake_on_result(this, status); - return status; + receiver.th->wake_on_result(this, status); + return status; } j6_status_t endpoint::receive(j6_tag_t *tag, size_t *len, void *data) { - thread_data receiver = { &thread::current(), data }; - receiver.tag_p = tag; - receiver.len_p = len; + thread_data receiver = { &thread::current(), data }; + receiver.tag_p = tag; + receiver.len_p = len; - if (!check_signal(j6_signal_endpoint_can_recv)) { - assert_signal(j6_signal_endpoint_can_send); - m_blocked.append(receiver); - receiver.th->wait_on_object(this); + if (!check_signal(j6_signal_endpoint_can_recv)) { + assert_signal(j6_signal_endpoint_can_send); + m_blocked.append(receiver); + receiver.th->wait_on_object(this); - // we woke up having already finished the recv - // because it happened in the sender - return receiver.th->get_wait_result(); - } + // we woke up having already finished the recv + // because it happened in the sender + return receiver.th->get_wait_result(); + } - thread_data sender = m_blocked.pop_front(); - if (m_blocked.count() == 0) - deassert_signal(j6_signal_endpoint_can_recv); + thread_data sender = m_blocked.pop_front(); + if (m_blocked.count() == 0) + deassert_signal(j6_signal_endpoint_can_recv); - // TODO: don't pop sender on some errors - j6_status_t status = do_message_copy(sender, receiver); + // TODO: don't pop sender on some errors + j6_status_t status = do_message_copy(sender, receiver); - if (sender.th) - sender.th->wake_on_result(this, status); + if (sender.th) + sender.th->wake_on_result(this, status); - return status; + return status; } void endpoint::signal_irq(unsigned irq) { - j6_tag_t tag = j6_tag_from_irq(irq); + j6_tag_t tag = j6_tag_from_irq(irq); - if (!check_signal(j6_signal_endpoint_can_send)) { - assert_signal(j6_signal_endpoint_can_recv); + if (!check_signal(j6_signal_endpoint_can_send)) { + assert_signal(j6_signal_endpoint_can_recv); - for (auto &blocked : m_blocked) - if (blocked.tag == tag) - return; + for (auto &blocked : m_blocked) + if (blocked.tag == tag) + return; - thread_data sender = { nullptr, nullptr }; - sender.tag = tag; - m_blocked.append(sender); - return; - } + thread_data sender = { nullptr, nullptr }; + sender.tag = tag; + m_blocked.append(sender); + return; + } - thread_data receiver = m_blocked.pop_front(); - if (m_blocked.count() == 0) - deassert_signal(j6_signal_endpoint_can_send); + thread_data receiver = m_blocked.pop_front(); + if (m_blocked.count() == 0) + deassert_signal(j6_signal_endpoint_can_send); - *receiver.len_p = 0; - *receiver.tag_p = tag; - receiver.th->wake_on_result(this, j6_status_ok); + *receiver.len_p = 0; + *receiver.tag_p = tag; + receiver.th->wake_on_result(this, j6_status_ok); } j6_status_t endpoint::do_message_copy(const endpoint::thread_data &sender, endpoint::thread_data &receiver) { - if (sender.len > *receiver.len_p) - return j6_err_insufficient; + if (sender.len > *receiver.len_p) + return j6_err_insufficient; - if (sender.len) { - vm_space &source = sender.th->parent().space(); - vm_space &dest = receiver.th->parent().space(); - vm_space::copy(source, dest, sender.data, receiver.data, sender.len); - } + if (sender.len) { + vm_space &source = sender.th->parent().space(); + vm_space &dest = receiver.th->parent().space(); + vm_space::copy(source, dest, sender.data, receiver.data, sender.len); + } - *receiver.len_p = sender.len; - *receiver.tag_p = sender.tag; + *receiver.len_p = sender.len; + *receiver.tag_p = sender.tag; - // TODO: this will not work if non-contiguous pages are mapped!! + // TODO: this will not work if non-contiguous pages are mapped!! - return j6_status_ok; + return j6_status_ok; } diff --git a/src/kernel/objects/endpoint.h b/src/kernel/objects/endpoint.h index 99c910d..993387a 100644 --- a/src/kernel/objects/endpoint.h +++ b/src/kernel/objects/endpoint.h @@ -7,59 +7,59 @@ /// Endpoints are objects that enable synchronous message-passing IPC class endpoint : - public kobject + public kobject { public: - endpoint(); - virtual ~endpoint(); + endpoint(); + virtual ~endpoint(); - static constexpr kobject::type type = kobject::type::endpoint; + static constexpr kobject::type type = kobject::type::endpoint; - /// Close the endpoint, waking all waiting processes with an error - virtual void close() override; + /// Close the endpoint, waking all waiting processes with an error + virtual void close() override; - /// Check if the endpoint has space for a message to be sent - inline bool can_send() const { return check_signal(j6_signal_endpoint_can_send); } + /// Check if the endpoint has space for a message to be sent + inline bool can_send() const { return check_signal(j6_signal_endpoint_can_send); } - /// Check if the endpoint has a message wiating already - inline bool can_receive() const { return check_signal(j6_signal_endpoint_can_recv); } + /// Check if the endpoint has a message wiating already + inline bool can_receive() const { return check_signal(j6_signal_endpoint_can_recv); } - /// Send a message to a thread waiting to receive on this endpoint. If no threads - /// are currently trying to receive, block the current thread. - /// \arg tag The application-specified message tag - /// \arg len The size in bytes of the message - /// \arg data The message data - /// \returns j6_status_ok on success - j6_status_t send(j6_tag_t tag, size_t len, void *data); + /// Send a message to a thread waiting to receive on this endpoint. If no threads + /// are currently trying to receive, block the current thread. + /// \arg tag The application-specified message tag + /// \arg len The size in bytes of the message + /// \arg data The message data + /// \returns j6_status_ok on success + j6_status_t send(j6_tag_t tag, size_t len, void *data); - /// Receive a message from a thread waiting to send on this endpoint. If no threads - /// are currently trying to send, block the current thread. - /// \arg tag [in] The sender-specified message tag - /// \arg len [in] The size in bytes of the buffer [out] Number of bytes in the message - /// \arg data Buffer for copying message data into - /// \returns j6_status_ok on success - j6_status_t receive(j6_tag_t *tag, size_t *len, void *data); + /// Receive a message from a thread waiting to send on this endpoint. If no threads + /// are currently trying to send, block the current thread. + /// \arg tag [in] The sender-specified message tag + /// \arg len [in] The size in bytes of the buffer [out] Number of bytes in the message + /// \arg data Buffer for copying message data into + /// \returns j6_status_ok on success + j6_status_t receive(j6_tag_t *tag, size_t *len, void *data); - /// Give the listener on the endpoint a message that a bound IRQ has been signalled - /// \arg irq The IRQ that caused this signal - void signal_irq(unsigned irq); + /// Give the listener on the endpoint a message that a bound IRQ has been signalled + /// \arg irq The IRQ that caused this signal + void signal_irq(unsigned irq); private: - struct thread_data - { - thread *th; - void *data; - union { - j6_tag_t *tag_p; - j6_tag_t tag; - }; - union { - size_t *len_p; - size_t len; - }; - }; + struct thread_data + { + thread *th; + void *data; + union { + j6_tag_t *tag_p; + j6_tag_t tag; + }; + union { + size_t *len_p; + size_t len; + }; + }; - j6_status_t do_message_copy(const thread_data &sender, thread_data &receiver); + j6_status_t do_message_copy(const thread_data &sender, thread_data &receiver); - kutil::vector m_blocked; + kutil::vector m_blocked; }; diff --git a/src/kernel/objects/event.h b/src/kernel/objects/event.h index 535fe90..1544e1c 100644 --- a/src/kernel/objects/event.h +++ b/src/kernel/objects/event.h @@ -5,11 +5,11 @@ #include "objects/kobject.h" class event : - public kobject + public kobject { public: - event() : - kobject(type::event) {} + event() : + kobject(type::event) {} - static constexpr kobject::type type = kobject::type::event; + static constexpr kobject::type type = kobject::type::event; }; diff --git a/src/kernel/objects/kobject.cpp b/src/kernel/objects/kobject.cpp index 6f3c254..af47df2 100644 --- a/src/kernel/objects/kobject.cpp +++ b/src/kernel/objects/kobject.cpp @@ -8,67 +8,67 @@ static j6_koid_t next_koids [static_cast(kobject::type::max)] = { 0 }; kobject::kobject(type t, j6_signal_t signals) : - m_koid(koid_generate(t)), - m_signals(signals), - m_handle_count(0) + m_koid(koid_generate(t)), + m_signals(signals), + m_handle_count(0) {} kobject::~kobject() { - for (auto *t : m_blocked_threads) - t->wake_on_result(this, j6_status_destroyed); + for (auto *t : m_blocked_threads) + t->wake_on_result(this, j6_status_destroyed); } j6_koid_t kobject::koid_generate(type t) { - kassert(t < type::max, "Object type out of bounds"); - uint64_t type_int = static_cast(t); - return (type_int << 48) | next_koids[type_int]++; + kassert(t < type::max, "Object type out of bounds"); + uint64_t type_int = static_cast(t); + return (type_int << 48) | next_koids[type_int]++; } kobject::type kobject::koid_type(j6_koid_t koid) { - return static_cast((koid >> 48) & 0xffffull); + return static_cast((koid >> 48) & 0xffffull); } void kobject::assert_signal(j6_signal_t s) { - m_signals |= s; - notify_signal_observers(); + m_signals |= s; + notify_signal_observers(); } void kobject::deassert_signal(j6_signal_t s) { - m_signals &= ~s; + m_signals &= ~s; } void kobject::notify_signal_observers() { - size_t i = 0; - while (i < m_blocked_threads.count()) { - thread *t = m_blocked_threads[i]; + size_t i = 0; + while (i < m_blocked_threads.count()) { + thread *t = m_blocked_threads[i]; - if (t->wake_on_signals(this, m_signals)) { - m_blocked_threads.remove_swap_at(i); - } else { - ++i; - } - } + if (t->wake_on_signals(this, m_signals)) { + m_blocked_threads.remove_swap_at(i); + } else { + ++i; + } + } } void kobject::close() { - assert_signal(j6_signal_closed); + assert_signal(j6_signal_closed); } void kobject::on_no_handles() { - assert_signal(j6_signal_no_handles); + assert_signal(j6_signal_no_handles); } diff --git a/src/kernel/objects/kobject.h b/src/kernel/objects/kobject.h index 9454fd1..e9d3379 100644 --- a/src/kernel/objects/kobject.h +++ b/src/kernel/objects/kobject.h @@ -13,88 +13,88 @@ class thread; class kobject { public: - /// Types of kernel objects. - enum class type : uint16_t - { + /// Types of kernel objects. + enum class type : uint16_t + { #define OBJECT_TYPE( name, val ) name = val, #include "j6/tables/object_types.inc" #undef OBJECT_TYPE - max - }; + max + }; - kobject(type t, j6_signal_t signals = 0ull); - virtual ~kobject(); + kobject(type t, j6_signal_t signals = 0ull); + virtual ~kobject(); - /// Generate a new koid for a given type - /// \arg t The object type - /// \returns A new unique koid - static j6_koid_t koid_generate(type t); + /// Generate a new koid for a given type + /// \arg t The object type + /// \returns A new unique koid + static j6_koid_t koid_generate(type t); - /// Get the kobject type from a given koid - /// \arg koid An existing koid - /// \returns The object type for the koid - static type koid_type(j6_koid_t koid); + /// Get the kobject type from a given koid + /// \arg koid An existing koid + /// \returns The object type for the koid + static type koid_type(j6_koid_t koid); - /// Get this object's type - inline type get_type() const { return koid_type(m_koid); } + /// Get this object's type + inline type get_type() const { return koid_type(m_koid); } - /// Get this object's koid - inline j6_koid_t koid() const { return m_koid; } + /// Get this object's koid + inline j6_koid_t koid() const { return m_koid; } - /// Set the given signals active on this object - /// \arg s The set of signals to assert - void assert_signal(j6_signal_t s); + /// Set the given signals active on this object + /// \arg s The set of signals to assert + void assert_signal(j6_signal_t s); - /// Clear the given signals on this object - /// \arg s The set of signals to deassert - void deassert_signal(j6_signal_t s); + /// Clear the given signals on this object + /// \arg s The set of signals to deassert + void deassert_signal(j6_signal_t s); - /// Check if the given signals are set on this object - /// \arg s The set of signals to check - inline bool check_signal(j6_signal_t s) const { return (m_signals & s) == s; } + /// Check if the given signals are set on this object + /// \arg s The set of signals to check + inline bool check_signal(j6_signal_t s) const { return (m_signals & s) == s; } - /// Get the current object signal state - inline j6_signal_t signals() const { return m_signals; } + /// Get the current object signal state + inline j6_signal_t signals() const { return m_signals; } - /// Increment the handle refcount - inline void handle_retain() { ++m_handle_count; } + /// Increment the handle refcount + inline void handle_retain() { ++m_handle_count; } - /// Decrement the handle refcount - inline void handle_release() { - if (--m_handle_count == 0) on_no_handles(); - } + /// Decrement the handle refcount + inline void handle_release() { + if (--m_handle_count == 0) on_no_handles(); + } - /// Add the given thread to the list of threads waiting on this object. - inline void add_blocked_thread(thread *t) { m_blocked_threads.append(t); } + /// Add the given thread to the list of threads waiting on this object. + inline void add_blocked_thread(thread *t) { m_blocked_threads.append(t); } - /// Remove the given thread from the list of threads waiting on this object. - inline void remove_blocked_thread(thread *t) { m_blocked_threads.remove_swap(t); } + /// Remove the given thread from the list of threads waiting on this object. + inline void remove_blocked_thread(thread *t) { m_blocked_threads.remove_swap(t); } - /// Perform any cleanup actions necessary to mark this object closed - virtual void close(); + /// Perform any cleanup actions necessary to mark this object closed + virtual void close(); - /// Check if this object has been closed - inline bool closed() const { return check_signal(j6_signal_closed); } + /// Check if this object has been closed + inline bool closed() const { return check_signal(j6_signal_closed); } protected: - /// Interface for subclasses to handle when all handles are closed. Subclasses - /// should either call the base version, or assert j6_signal_no_handles. - virtual void on_no_handles(); + /// Interface for subclasses to handle when all handles are closed. Subclasses + /// should either call the base version, or assert j6_signal_no_handles. + virtual void on_no_handles(); private: - kobject() = delete; - kobject(const kobject &other) = delete; - kobject(const kobject &&other) = delete; + kobject() = delete; + kobject(const kobject &other) = delete; + kobject(const kobject &&other) = delete; - /// Notifiy observers of this object - /// \arg result The result to pass to the observers - void notify_signal_observers(); + /// Notifiy observers of this object + /// \arg result The result to pass to the observers + void notify_signal_observers(); - j6_koid_t m_koid; - j6_signal_t m_signals; - uint16_t m_handle_count; + j6_koid_t m_koid; + j6_signal_t m_signals; + uint16_t m_handle_count; protected: - kutil::vector m_blocked_threads; + kutil::vector m_blocked_threads; }; diff --git a/src/kernel/objects/process.cpp b/src/kernel/objects/process.cpp index 46d4be2..300e601 100644 --- a/src/kernel/objects/process.cpp +++ b/src/kernel/objects/process.cpp @@ -14,27 +14,27 @@ process &g_kernel_process = __g_kernel_process_storage.value; process::process() : - kobject {kobject::type::process}, - m_next_handle {1}, - m_state {state::running} + kobject {kobject::type::process}, + m_next_handle {1}, + m_state {state::running} { - j6_handle_t self = add_handle(this); - kassert(self == self_handle(), "Process self-handle is not 1"); + j6_handle_t self = add_handle(this); + kassert(self == self_handle(), "Process self-handle is not 1"); } // The "kernel process"-only constructor process::process(page_table *kpml4) : - kobject {kobject::type::process}, - m_space {kpml4}, - m_next_handle {self_handle()+1}, - m_state {state::running} + kobject {kobject::type::process}, + m_space {kpml4}, + m_next_handle {self_handle()+1}, + m_state {state::running} { } process::~process() { - for (auto &it : m_handles) - if (it.val) it.val->handle_release(); + for (auto &it : m_handles) + if (it.val) it.val->handle_release(); } process & process::current() { return *current_cpu().process; } @@ -43,115 +43,115 @@ process & process::kernel_process() { return g_kernel_process; } process * process::create_kernel_process(page_table *pml4) { - return new (&g_kernel_process) process {pml4}; + return new (&g_kernel_process) process {pml4}; } void process::exit(int32_t code) { - // TODO: make this thread-safe - m_state = state::exited; - m_return_code = code; - close(); + // TODO: make this thread-safe + m_state = state::exited; + m_return_code = code; + close(); - for (auto *thread : m_threads) { - thread->exit(code); - } + for (auto *thread : m_threads) { + thread->exit(code); + } - if (this == current_cpu().process) - scheduler::get().schedule(); + if (this == current_cpu().process) + scheduler::get().schedule(); } void process::update() { - kassert(m_threads.count() > 0, "process::update with zero threads!"); + kassert(m_threads.count() > 0, "process::update with zero threads!"); - size_t i = 0; - uint32_t status = 0; - while (i < m_threads.count()) { - thread *th = m_threads[i]; - if (th->has_state(thread::state::exited)) { - status = th->m_return_code; - m_threads.remove_swap_at(i); - continue; - } - i++; - } + size_t i = 0; + uint32_t status = 0; + while (i < m_threads.count()) { + thread *th = m_threads[i]; + if (th->has_state(thread::state::exited)) { + status = th->m_return_code; + m_threads.remove_swap_at(i); + continue; + } + i++; + } - if (m_threads.count() == 0) { - // TODO: What really is the return code in this case? - exit(status); - } + if (m_threads.count() == 0) { + // TODO: What really is the return code in this case? + exit(status); + } } thread * process::create_thread(uint8_t priority, bool user) { - if (priority == default_priority) - priority = scheduler::default_priority; + if (priority == default_priority) + priority = scheduler::default_priority; - thread *th = new thread(*this, priority); - kassert(th, "Failed to create thread!"); + thread *th = new thread(*this, priority); + kassert(th, "Failed to create thread!"); - if (user) { - uintptr_t stack_top = stacks_top - (m_threads.count() * stack_size); + if (user) { + uintptr_t stack_top = stacks_top - (m_threads.count() * stack_size); - vm_flags flags = vm_flags::zero|vm_flags::write; - vm_area *vma = new vm_area_open(stack_size, flags); - m_space.add(stack_top - stack_size, vma); + vm_flags flags = vm_flags::zero|vm_flags::write; + vm_area *vma = new vm_area_open(stack_size, flags); + m_space.add(stack_top - stack_size, vma); - // Space for null frame - because the page gets zeroed on - // allocation, just pointing rsp here does the trick - th->tcb()->rsp3 = stack_top - 2 * sizeof(uint64_t); - } + // Space for null frame - because the page gets zeroed on + // allocation, just pointing rsp here does the trick + th->tcb()->rsp3 = stack_top - 2 * sizeof(uint64_t); + } - m_threads.append(th); - scheduler::get().add_thread(th->tcb()); - return th; + m_threads.append(th); + scheduler::get().add_thread(th->tcb()); + return th; } bool process::thread_exited(thread *th) { - kassert(&th->m_parent == this, "Process got thread_exited for non-child!"); - uint32_t status = th->m_return_code; - m_threads.remove_swap(th); - remove_handle(th->self_handle()); - delete th; + kassert(&th->m_parent == this, "Process got thread_exited for non-child!"); + uint32_t status = th->m_return_code; + m_threads.remove_swap(th); + remove_handle(th->self_handle()); + delete th; - // TODO: delete the thread's stack VMA + // TODO: delete the thread's stack VMA - if (m_threads.count() == 0) { - exit(status); - return true; - } + if (m_threads.count() == 0) { + exit(status); + return true; + } - return false; + return false; } j6_handle_t process::add_handle(kobject *obj) { - if (!obj) - return j6_handle_invalid; + if (!obj) + return j6_handle_invalid; - obj->handle_retain(); - j6_handle_t handle = m_next_handle++; - m_handles.insert(handle, obj); - return handle; + obj->handle_retain(); + j6_handle_t handle = m_next_handle++; + m_handles.insert(handle, obj); + return handle; } bool process::remove_handle(j6_handle_t handle) { - kobject *obj = m_handles.find(handle); - if (obj) obj->handle_release(); - return m_handles.erase(handle); + kobject *obj = m_handles.find(handle); + if (obj) obj->handle_release(); + return m_handles.erase(handle); } kobject * process::lookup_handle(j6_handle_t handle) { - return m_handles.find(handle); + return m_handles.find(handle); } diff --git a/src/kernel/objects/process.h b/src/kernel/objects/process.h index 053638a..f1586cb 100644 --- a/src/kernel/objects/process.h +++ b/src/kernel/objects/process.h @@ -9,89 +9,89 @@ #include "vm_space.h" class process : - public kobject + public kobject { public: - /// Top of memory area where thread stacks are allocated - constexpr static uintptr_t stacks_top = 0x0000800000000000; + /// Top of memory area where thread stacks are allocated + constexpr static uintptr_t stacks_top = 0x0000800000000000; - /// Size of userspace thread stacks - constexpr static size_t stack_size = 0x4000000; // 64MiB + /// Size of userspace thread stacks + constexpr static size_t stack_size = 0x4000000; // 64MiB - /// Value that represents default priority - constexpr static uint8_t default_priority = 0xff; + /// Value that represents default priority + constexpr static uint8_t default_priority = 0xff; - /// Constructor. - process(); + /// Constructor. + process(); - /// Destructor. - virtual ~process(); + /// Destructor. + virtual ~process(); - static constexpr kobject::type type = kobject::type::process; + static constexpr kobject::type type = kobject::type::process; - /// Get the currently executing process. - static process & current(); + /// Get the currently executing process. + static process & current(); - /// Terminate this process. - /// \arg code The return code to exit with. - void exit(int32_t code); + /// Terminate this process. + /// \arg code The return code to exit with. + void exit(int32_t code); - /// Update internal bookkeeping about threads. - void update(); + /// Update internal bookkeeping about threads. + void update(); - /// Get the process' virtual memory space - vm_space & space() { return m_space; } + /// Get the process' virtual memory space + vm_space & space() { return m_space; } - /// Create a new thread in this process - /// \args priority The new thread's scheduling priority - /// \args user If true, create a userspace stack for this thread - /// \returns The newly created thread object - thread * create_thread(uint8_t priorty = default_priority, bool user = true); + /// Create a new thread in this process + /// \args priority The new thread's scheduling priority + /// \args user If true, create a userspace stack for this thread + /// \returns The newly created thread object + thread * create_thread(uint8_t priorty = default_priority, bool user = true); - /// Start tracking an object with a handle. - /// \args obj The object this handle refers to - /// \returns The new handle for this object - j6_handle_t add_handle(kobject *obj); + /// Start tracking an object with a handle. + /// \args obj The object this handle refers to + /// \returns The new handle for this object + j6_handle_t add_handle(kobject *obj); - /// Stop tracking an object with a handle. - /// \args handle The handle that refers to the object - /// \returns True if the handle was removed - bool remove_handle(j6_handle_t handle); + /// Stop tracking an object with a handle. + /// \args handle The handle that refers to the object + /// \returns True if the handle was removed + bool remove_handle(j6_handle_t handle); - /// Lookup an object for a handle - /// \args handle The handle to the object - /// \returns Pointer to the object, or null if not found - kobject * lookup_handle(j6_handle_t handle); + /// Lookup an object for a handle + /// \args handle The handle to the object + /// \returns Pointer to the object, or null if not found + kobject * lookup_handle(j6_handle_t handle); - /// Inform the process of an exited thread - /// \args th The thread which has exited - /// \returns True if this thread ending has ended the process - bool thread_exited(thread *th); + /// Inform the process of an exited thread + /// \args th The thread which has exited + /// \returns True if this thread ending has ended the process + bool thread_exited(thread *th); - /// Get the handle for this process to refer to itself - inline j6_handle_t self_handle() const { return 1; } + /// Get the handle for this process to refer to itself + inline j6_handle_t self_handle() const { return 1; } - /// Get the process object that owns kernel threads and the - /// kernel address space - static process & kernel_process(); + /// Get the process object that owns kernel threads and the + /// kernel address space + static process & kernel_process(); - /// Create the special kernel process that owns kernel tasks - /// \arg pml4 The kernel-only pml4 - /// \returns The kernel process object - static process * create_kernel_process(page_table *pml4); + /// Create the special kernel process that owns kernel tasks + /// \arg pml4 The kernel-only pml4 + /// \returns The kernel process object + static process * create_kernel_process(page_table *pml4); private: - // This constructor is called by create_kernel_process - process(page_table *kpml4); + // This constructor is called by create_kernel_process + process(page_table *kpml4); - int32_t m_return_code; + int32_t m_return_code; - vm_space m_space; + vm_space m_space; - kutil::vector m_threads; - kutil::map m_handles; - j6_handle_t m_next_handle; + kutil::vector m_threads; + kutil::map m_handles; + j6_handle_t m_next_handle; - enum class state : uint8_t { running, exited }; - state m_state; + enum class state : uint8_t { running, exited }; + state m_state; }; diff --git a/src/kernel/objects/system.h b/src/kernel/objects/system.h index 0367d17..b68cb89 100644 --- a/src/kernel/objects/system.h +++ b/src/kernel/objects/system.h @@ -5,14 +5,14 @@ #include "objects/kobject.h" class system : - public kobject + public kobject { public: - static constexpr kobject::type type = kobject::type::event; + static constexpr kobject::type type = kobject::type::event; - inline static system & get() { return s_instance; } + inline static system & get() { return s_instance; } private: - static system s_instance; - system() : kobject(type::system) {} + static system s_instance; + system() : kobject(type::system) {} }; diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index 6b03abc..473486d 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -12,35 +12,35 @@ static constexpr j6_signal_t thread_default_signals = 0; extern vm_area_guarded &g_kernel_stacks; thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) : - kobject(kobject::type::thread, thread_default_signals), - m_parent(parent), - m_state(state::loading), - m_wait_type(wait_type::none), - m_wait_data(0), - m_wait_obj(0) + kobject(kobject::type::thread, thread_default_signals), + m_parent(parent), + m_state(state::loading), + m_wait_type(wait_type::none), + m_wait_data(0), + m_wait_obj(0) { - parent.space().initialize_tcb(m_tcb); - m_tcb.priority = pri; + parent.space().initialize_tcb(m_tcb); + m_tcb.priority = pri; - if (!rsp0) - setup_kernel_stack(); - else - m_tcb.rsp0 = rsp0; + if (!rsp0) + setup_kernel_stack(); + else + m_tcb.rsp0 = rsp0; - m_self_handle = parent.add_handle(this); + m_self_handle = parent.add_handle(this); } thread::~thread() { - g_kernel_stacks.return_section(m_tcb.kernel_stack); + g_kernel_stacks.return_section(m_tcb.kernel_stack); } thread * thread::from_tcb(TCB *tcb) { - static ptrdiff_t offset = - -1 * static_cast(offsetof(thread, m_tcb)); - return reinterpret_cast(kutil::offset_pointer(tcb, offset)); + static ptrdiff_t offset = + -1 * static_cast(offsetof(thread, m_tcb)); + return reinterpret_cast(kutil::offset_pointer(tcb, offset)); } thread & thread::current() { return *current_cpu().thread; } @@ -50,176 +50,176 @@ inline void schedule_if_current(thread *t) { if (t == current_cpu().thread) sche void thread::wait_on_signals(j6_signal_t signals) { - m_wait_type = wait_type::signal; - m_wait_data = signals; - clear_state(state::ready); + m_wait_type = wait_type::signal; + m_wait_data = signals; + clear_state(state::ready); - schedule_if_current(this); + schedule_if_current(this); } void thread::wait_on_time(uint64_t t) { - m_wait_type = wait_type::time; - m_wait_data = t; - clear_state(state::ready); + m_wait_type = wait_type::time; + m_wait_data = t; + clear_state(state::ready); - schedule_if_current(this); + schedule_if_current(this); } void thread::wait_on_object(kobject *o) { - m_wait_type = wait_type::object; - m_wait_data = reinterpret_cast(o); - clear_state(state::ready); + m_wait_type = wait_type::object; + m_wait_data = reinterpret_cast(o); + clear_state(state::ready); - schedule_if_current(this); + schedule_if_current(this); } bool thread::wake_on_signals(kobject *obj, j6_signal_t signals) { - if (m_wait_type != wait_type::signal || - (signals & m_wait_data) == 0) - return false; + if (m_wait_type != wait_type::signal || + (signals & m_wait_data) == 0) + return false; - m_wait_type = wait_type::none; - m_wait_result = j6_status_ok; - m_wait_data = signals; - m_wait_obj = obj->koid(); - set_state(state::ready); - return true; + m_wait_type = wait_type::none; + m_wait_result = j6_status_ok; + m_wait_data = signals; + m_wait_obj = obj->koid(); + set_state(state::ready); + return true; } bool thread::wake_on_time(uint64_t now) { - if (m_wait_type != wait_type::time || - now < m_wait_data) - return false; + if (m_wait_type != wait_type::time || + now < m_wait_data) + return false; - m_wait_type = wait_type::none; - m_wait_result = j6_status_ok; - m_wait_data = now; - m_wait_obj = 0; - set_state(state::ready); - return true; + m_wait_type = wait_type::none; + m_wait_result = j6_status_ok; + m_wait_data = now; + m_wait_obj = 0; + set_state(state::ready); + return true; } bool thread::wake_on_object(kobject *o) { - if (m_wait_type != wait_type::object || - reinterpret_cast(o) != m_wait_data) - return false; + if (m_wait_type != wait_type::object || + reinterpret_cast(o) != m_wait_data) + return false; - m_wait_type = wait_type::none; - m_wait_result = j6_status_ok; - m_wait_obj = o->koid(); - set_state(state::ready); - return true; + m_wait_type = wait_type::none; + m_wait_result = j6_status_ok; + m_wait_obj = o->koid(); + set_state(state::ready); + return true; } void thread::wake_on_result(kobject *obj, j6_status_t result) { - m_wait_type = wait_type::none; - m_wait_result = result; - m_wait_data = 0; - m_wait_obj = obj->koid(); - set_state(state::ready); + m_wait_type = wait_type::none; + m_wait_result = result; + m_wait_data = 0; + m_wait_obj = obj->koid(); + set_state(state::ready); } void thread::exit(int32_t code) { - m_return_code = code; - set_state(state::exited); - clear_state(state::ready); - close(); + m_return_code = code; + set_state(state::exited); + clear_state(state::ready); + close(); - schedule_if_current(this); + schedule_if_current(this); } void thread::add_thunk_kernel(uintptr_t rip) { - // This adds just enough values to the top of the - // kernel stack to come out of task_switch correctly - // and start executing at rip (still in kernel mode) + // This adds just enough values to the top of the + // kernel stack to come out of task_switch correctly + // and start executing at rip (still in kernel mode) - m_tcb.rsp -= sizeof(uintptr_t) * 7; - uintptr_t *stack = reinterpret_cast(m_tcb.rsp); + m_tcb.rsp -= sizeof(uintptr_t) * 7; + uintptr_t *stack = reinterpret_cast(m_tcb.rsp); - stack[6] = rip; // return rip - stack[5] = m_tcb.rsp0; // rbp - stack[4] = 0xbbbbbbbb; // rbx - stack[3] = 0x12121212; // r12 - stack[2] = 0x13131313; // r13 - stack[1] = 0x14141414; // r14 - stack[0] = 0x15151515; // r15 + stack[6] = rip; // return rip + stack[5] = m_tcb.rsp0; // rbp + stack[4] = 0xbbbbbbbb; // rbx + stack[3] = 0x12121212; // r12 + stack[2] = 0x13131313; // r13 + stack[1] = 0x14141414; // r14 + stack[0] = 0x15151515; // r15 } void thread::add_thunk_user(uintptr_t rip3, uintptr_t rip0, uint64_t flags) { - // This sets up the stack to: - // a) come out of task_switch and return to rip0 (default is the - // kernel/user trampoline) (via add_thunk_kernel) - if this is - // changed, it needs to end up at the trampoline with the stack - // as it was - // b) come out of the kernel/user trampoline and start executing - // in user mode at rip + // This sets up the stack to: + // a) come out of task_switch and return to rip0 (default is the + // kernel/user trampoline) (via add_thunk_kernel) - if this is + // changed, it needs to end up at the trampoline with the stack + // as it was + // b) come out of the kernel/user trampoline and start executing + // in user mode at rip - m_tcb.rsp -= sizeof(uintptr_t) * 8; - uintptr_t *stack = reinterpret_cast(m_tcb.rsp); - flags |= 0x200; + m_tcb.rsp -= sizeof(uintptr_t) * 8; + uintptr_t *stack = reinterpret_cast(m_tcb.rsp); + flags |= 0x200; - stack[7] = rip3; // return rip in rcx - stack[6] = m_tcb.rsp3; // rbp - stack[5] = 0xbbbbbbbb; // rbx - stack[4] = flags; // r11 sets RFLAGS - stack[3] = 0x12121212; // r12 - stack[2] = 0x13131313; // r13 - stack[1] = 0x14141414; // r14 - stack[0] = 0x15151515; // r15 + stack[7] = rip3; // return rip in rcx + stack[6] = m_tcb.rsp3; // rbp + stack[5] = 0xbbbbbbbb; // rbx + stack[4] = flags; // r11 sets RFLAGS + stack[3] = 0x12121212; // r12 + stack[2] = 0x13131313; // r13 + stack[1] = 0x14141414; // r14 + stack[0] = 0x15151515; // r15 - static const uintptr_t trampoline = - reinterpret_cast(kernel_to_user_trampoline); - add_thunk_kernel(rip0 ? rip0 : trampoline); + static const uintptr_t trampoline = + reinterpret_cast(kernel_to_user_trampoline); + add_thunk_kernel(rip0 ? rip0 : trampoline); } void thread::setup_kernel_stack() { - using memory::frame_size; - using memory::kernel_stack_pages; - static constexpr size_t stack_bytes = kernel_stack_pages * frame_size; + using memory::frame_size; + using memory::kernel_stack_pages; + static constexpr size_t stack_bytes = kernel_stack_pages * frame_size; - constexpr unsigned null_frame_entries = 2; - constexpr size_t null_frame_size = null_frame_entries * sizeof(uint64_t); + constexpr unsigned null_frame_entries = 2; + constexpr size_t null_frame_size = null_frame_entries * sizeof(uint64_t); - uintptr_t stack_addr = g_kernel_stacks.get_section(); - uintptr_t stack_end = stack_addr + stack_bytes; + uintptr_t stack_addr = g_kernel_stacks.get_section(); + uintptr_t stack_end = stack_addr + stack_bytes; - uint64_t *null_frame = reinterpret_cast(stack_end - null_frame_size); - for (unsigned i = 0; i < null_frame_entries; ++i) - null_frame[i] = 0; + uint64_t *null_frame = reinterpret_cast(stack_end - null_frame_size); + for (unsigned i = 0; i < null_frame_entries; ++i) + null_frame[i] = 0; - log::debug(logs::memory, "Created kernel stack at %016lx size 0x%lx", - stack_addr, stack_bytes); + log::debug(logs::memory, "Created kernel stack at %016lx size 0x%lx", + stack_addr, stack_bytes); - m_tcb.kernel_stack = stack_addr; - m_tcb.rsp0 = reinterpret_cast(null_frame); - m_tcb.rsp = m_tcb.rsp0; + m_tcb.kernel_stack = stack_addr; + m_tcb.rsp0 = reinterpret_cast(null_frame); + m_tcb.rsp = m_tcb.rsp0; } thread * thread::create_idle_thread(process &kernel, uint8_t pri, uintptr_t rsp0) { - thread *idle = new thread(kernel, pri, rsp0); - idle->set_state(state::constant); - idle->set_state(state::ready); - return idle; + thread *idle = new thread(kernel, pri, rsp0); + idle->set_state(state::constant); + idle->set_state(state::ready); + return idle; } diff --git a/src/kernel/objects/thread.h b/src/kernel/objects/thread.h index b3fe11c..172abe8 100644 --- a/src/kernel/objects/thread.h +++ b/src/kernel/objects/thread.h @@ -10,179 +10,179 @@ class process; struct TCB { - // Data used by assembly task control routines. If you change any of these, - // be sure to change the assembly definitions in 'tasking.inc' - uintptr_t rsp; - uintptr_t rsp0; - uintptr_t rsp3; - uintptr_t pml4; + // Data used by assembly task control routines. If you change any of these, + // be sure to change the assembly definitions in 'tasking.inc' + uintptr_t rsp; + uintptr_t rsp0; + uintptr_t rsp3; + uintptr_t pml4; - uint8_t priority; - // note: 3 bytes padding + uint8_t priority; + // note: 3 bytes padding - // TODO: move state into TCB? + // TODO: move state into TCB? - uintptr_t kernel_stack; + uintptr_t kernel_stack; - uint32_t time_left; - uint64_t last_ran; + uint32_t time_left; + uint64_t last_ran; }; using tcb_list = kutil::linked_list; using tcb_node = tcb_list::item_type; class thread : - public kobject + public kobject { public: - enum class wait_type : uint8_t { none, signal, time, object }; - enum class state : uint8_t { - ready = 0x01, - loading = 0x02, - exited = 0x04, - constant = 0x80, - none = 0x00 - }; + enum class wait_type : uint8_t { none, signal, time, object }; + enum class state : uint8_t { + ready = 0x01, + loading = 0x02, + exited = 0x04, + constant = 0x80, + none = 0x00 + }; - /// Get the pointer to the thread object containing this TCB - static thread * from_tcb(TCB *tcb); + /// Get the pointer to the thread object containing this TCB + static thread * from_tcb(TCB *tcb); - /// Destructor - virtual ~thread(); + /// Destructor + virtual ~thread(); - static constexpr kobject::type type = kobject::type::thread; + static constexpr kobject::type type = kobject::type::thread; - /// Get the currently executing thread. - static thread & current(); + /// Get the currently executing thread. + static thread & current(); - /// Get the `ready` state of the thread. - /// \returns True if the thread is ready to execute. - inline bool ready() const { return has_state(state::ready); } + /// Get the `ready` state of the thread. + /// \returns True if the thread is ready to execute. + inline bool ready() const { return has_state(state::ready); } - /// Get the `loading` state of the thread. - /// \returns True if the thread has not finished loading. - inline bool loading() const { return has_state(state::loading); } + /// Get the `loading` state of the thread. + /// \returns True if the thread has not finished loading. + inline bool loading() const { return has_state(state::loading); } - /// Get the `constant` state of the thread. - /// \returns True if the thread has constant priority. - inline bool constant() const { return has_state(state::constant); } + /// Get the `constant` state of the thread. + /// \returns True if the thread has constant priority. + inline bool constant() const { return has_state(state::constant); } - /// Get the thread priority. - inline uint8_t priority() const { return m_tcb.priority; } + /// Get the thread priority. + inline uint8_t priority() const { return m_tcb.priority; } - /// Set the thread priority. - /// \arg p The new thread priority - inline void set_priority(uint8_t p) { if (!constant()) m_tcb.priority = p; } + /// Set the thread priority. + /// \arg p The new thread priority + inline void set_priority(uint8_t p) { if (!constant()) m_tcb.priority = p; } - /// Block the thread, waiting an object's signals. - /// \arg signals Mask of signals to wait for - void wait_on_signals(j6_signal_t signals); + /// Block the thread, waiting an object's signals. + /// \arg signals Mask of signals to wait for + void wait_on_signals(j6_signal_t signals); - /// Block the thread, waiting for a given clock value - /// \arg t Clock value to wait for - void wait_on_time(uint64_t t); + /// Block the thread, waiting for a given clock value + /// \arg t Clock value to wait for + void wait_on_time(uint64_t t); - /// Block the thread, waiting on the given object - /// \arg o The ojbect that should wake this thread - void wait_on_object(kobject *o); + /// Block the thread, waiting on the given object + /// \arg o The ojbect that should wake this thread + void wait_on_object(kobject *o); - /// Wake the thread if it is waiting on signals. - /// \arg obj Object that changed signals - /// \arg signals Signal state of the object - /// \returns True if this action unblocked the thread - bool wake_on_signals(kobject *obj, j6_signal_t signals); + /// Wake the thread if it is waiting on signals. + /// \arg obj Object that changed signals + /// \arg signals Signal state of the object + /// \returns True if this action unblocked the thread + bool wake_on_signals(kobject *obj, j6_signal_t signals); - /// Wake the thread if it is waiting on the clock. - /// \arg now Current clock value - /// \returns True if this action unblocked the thread - bool wake_on_time(uint64_t now); + /// Wake the thread if it is waiting on the clock. + /// \arg now Current clock value + /// \returns True if this action unblocked the thread + bool wake_on_time(uint64_t now); - /// Wake the thread if it is waiting on the given object. - /// \arg o Object trying to wake the thread - /// \returns True if this action unblocked the thread - bool wake_on_object(kobject *o); + /// Wake the thread if it is waiting on the given object. + /// \arg o Object trying to wake the thread + /// \returns True if this action unblocked the thread + bool wake_on_object(kobject *o); - /// Wake the thread with a given result code. - /// \arg obj Object that changed signals - /// \arg result Result code to return to the thread - void wake_on_result(kobject *obj, j6_status_t result); + /// Wake the thread with a given result code. + /// \arg obj Object that changed signals + /// \arg result Result code to return to the thread + void wake_on_result(kobject *obj, j6_status_t result); - /// Get the result status code from the last blocking operation - j6_status_t get_wait_result() const { return m_wait_result; } + /// Get the result status code from the last blocking operation + j6_status_t get_wait_result() const { return m_wait_result; } - /// Get the current blocking opreation's wait data - uint64_t get_wait_data() const { return m_wait_data; } + /// Get the current blocking opreation's wait data + uint64_t get_wait_data() const { return m_wait_data; } /// Get the current blocking operation's wait ojbect (as a handle) - j6_koid_t get_wait_object() const { return m_wait_obj; } + j6_koid_t get_wait_object() const { return m_wait_obj; } - inline bool has_state(state s) const { - return static_cast(m_state) & static_cast(s); - } + inline bool has_state(state s) const { + return static_cast(m_state) & static_cast(s); + } - inline void set_state(state s) { - m_state = static_cast(static_cast(m_state) | static_cast(s)); - } + inline void set_state(state s) { + m_state = static_cast(static_cast(m_state) | static_cast(s)); + } - inline void clear_state(state s) { - m_state = static_cast(static_cast(m_state) & ~static_cast(s)); - } + inline void clear_state(state s) { + m_state = static_cast(static_cast(m_state) & ~static_cast(s)); + } - inline tcb_node * tcb() { return &m_tcb; } - inline process & parent() { return m_parent; } + inline tcb_node * tcb() { return &m_tcb; } + inline process & parent() { return m_parent; } - /// Terminate this thread. - /// \arg code The return code to exit with. - void exit(int32_t code); + /// Terminate this thread. + /// \arg code The return code to exit with. + void exit(int32_t code); - /// Add a stack header that returns to the given address in kernel space. - /// \arg rip The address to return to, must be kernel space - void add_thunk_kernel(uintptr_t rip); + /// Add a stack header that returns to the given address in kernel space. + /// \arg rip The address to return to, must be kernel space + void add_thunk_kernel(uintptr_t rip); - /// Add a stack header that returns to the given address in user space - /// via a function in kernel space. - /// \arg rip3 The user space address to return to - /// \arg rip0 The kernel function to pass through, optional - /// \arg flags Extra RFLAGS values to set, optional - void add_thunk_user(uintptr_t rip3, uintptr_t rip0 = 0, uint64_t flags = 0); + /// Add a stack header that returns to the given address in user space + /// via a function in kernel space. + /// \arg rip3 The user space address to return to + /// \arg rip0 The kernel function to pass through, optional + /// \arg flags Extra RFLAGS values to set, optional + void add_thunk_user(uintptr_t rip3, uintptr_t rip0 = 0, uint64_t flags = 0); - /// Get the handle representing this thread to its process - j6_handle_t self_handle() const { return m_self_handle; } + /// Get the handle representing this thread to its process + j6_handle_t self_handle() const { return m_self_handle; } - /// Create the kernel idle thread - /// \arg kernel The process object that owns kernel tasks - /// \arg pri The idle thread priority value - /// \arg rsp The existing stack for the idle thread - static thread * create_idle_thread(process &kernel, uint8_t pri, uintptr_t rsp); + /// Create the kernel idle thread + /// \arg kernel The process object that owns kernel tasks + /// \arg pri The idle thread priority value + /// \arg rsp The existing stack for the idle thread + static thread * create_idle_thread(process &kernel, uint8_t pri, uintptr_t rsp); private: - thread() = delete; - thread(const thread &other) = delete; - thread(const thread &&other) = delete; - friend class process; + thread() = delete; + thread(const thread &other) = delete; + thread(const thread &&other) = delete; + friend class process; - /// Constructor. Used when a kernel stack already exists. - /// \arg parent The process which owns this thread - /// \arg pri Initial priority level of this thread - /// \arg rsp0 The existing kernel stack rsp, 0 for none - thread(process &parent, uint8_t pri, uintptr_t rsp0 = 0); + /// Constructor. Used when a kernel stack already exists. + /// \arg parent The process which owns this thread + /// \arg pri Initial priority level of this thread + /// \arg rsp0 The existing kernel stack rsp, 0 for none + thread(process &parent, uint8_t pri, uintptr_t rsp0 = 0); - /// Set up a new empty kernel stack for this thread. - void setup_kernel_stack(); + /// Set up a new empty kernel stack for this thread. + void setup_kernel_stack(); - tcb_node m_tcb; + tcb_node m_tcb; - process &m_parent; + process &m_parent; - state m_state; - wait_type m_wait_type; - // There should be 1 byte of padding here + state m_state; + wait_type m_wait_type; + // There should be 1 byte of padding here - int32_t m_return_code; + int32_t m_return_code; - uint64_t m_wait_data; - j6_status_t m_wait_result; - j6_koid_t m_wait_obj; + uint64_t m_wait_data; + j6_status_t m_wait_result; + j6_koid_t m_wait_obj; - j6_handle_t m_self_handle; + j6_handle_t m_self_handle; }; diff --git a/src/kernel/objects/vm_area.cpp b/src/kernel/objects/vm_area.cpp index c5609fc..01f4dfa 100644 --- a/src/kernel/objects/vm_area.cpp +++ b/src/kernel/objects/vm_area.cpp @@ -7,10 +7,10 @@ using memory::frame_size; vm_area::vm_area(size_t size, vm_flags flags) : - m_size {size}, - m_flags {flags}, - m_spaces {m_vector_static, 0, static_size}, - kobject {kobject::type::vma} + m_size {size}, + m_flags {flags}, + m_spaces {m_vector_static, 0, static_size}, + kobject {kobject::type::vma} { } @@ -19,50 +19,50 @@ vm_area::~vm_area() {} bool vm_area::add_to(vm_space *space) { - for (auto *s : m_spaces) { - if (s == space) - return true; - } - m_spaces.append(space); - return true; + for (auto *s : m_spaces) { + if (s == space) + return true; + } + m_spaces.append(space); + return true; } bool vm_area::remove_from(vm_space *space) { - m_spaces.remove_swap(space); - return - !m_spaces.count() && - !(m_flags && vm_flags::mmio); + m_spaces.remove_swap(space); + return + !m_spaces.count() && + !(m_flags && vm_flags::mmio); } void vm_area::on_no_handles() { - kobject::on_no_handles(); - delete this; + kobject::on_no_handles(); + delete this; } size_t vm_area::resize(size_t size) { - if (can_resize(size)) - m_size = size; - return m_size; + if (can_resize(size)) + m_size = size; + return m_size; } bool vm_area::can_resize(size_t size) { - for (auto *space : m_spaces) - if (!space->can_resize(*this, size)) - return false; - return true; + for (auto *space : m_spaces) + if (!space->can_resize(*this, size)) + return false; + return true; } vm_area_fixed::vm_area_fixed(uintptr_t start, size_t size, vm_flags flags) : - m_start {start}, - vm_area {size, flags} + m_start {start}, + vm_area {size, flags} { } @@ -70,22 +70,22 @@ vm_area_fixed::~vm_area_fixed() {} size_t vm_area_fixed::resize(size_t size) { - // Not resizable - return m_size; + // Not resizable + return m_size; } bool vm_area_fixed::get_page(uintptr_t offset, uintptr_t &phys) { - if (offset > m_size) - return false; + if (offset > m_size) + return false; - phys = m_start + offset; - return true; + phys = m_start + offset; + return true; } vm_area_untracked::vm_area_untracked(size_t size, vm_flags flags) : - vm_area {size, flags} + vm_area {size, flags} { } @@ -94,24 +94,24 @@ vm_area_untracked::~vm_area_untracked() {} bool vm_area_untracked::get_page(uintptr_t offset, uintptr_t &phys) { - if (offset > m_size) - return false; + if (offset > m_size) + return false; - return frame_allocator::get().allocate(1, &phys); + return frame_allocator::get().allocate(1, &phys); } bool vm_area_untracked::add_to(vm_space *space) { - if (!m_spaces.count()) - return vm_area::add_to(space); - return m_spaces[0] == space; + if (!m_spaces.count()) + return vm_area::add_to(space); + return m_spaces[0] == space; } vm_area_open::vm_area_open(size_t size, vm_flags flags) : - m_mapped {nullptr}, - vm_area {size, flags} + m_mapped {nullptr}, + vm_area {size, flags} { } @@ -120,15 +120,15 @@ vm_area_open::~vm_area_open() {} bool vm_area_open::get_page(uintptr_t offset, uintptr_t &phys) { - return page_tree::find_or_add(m_mapped, offset, phys); + return page_tree::find_or_add(m_mapped, offset, phys); } vm_area_guarded::vm_area_guarded(uintptr_t start, size_t buf_pages, size_t size, vm_flags flags) : - m_start {start}, - m_pages {buf_pages}, - m_next {memory::frame_size}, - vm_area_untracked {size, flags} + m_start {start}, + m_pages {buf_pages}, + m_next {memory::frame_size}, + vm_area_untracked {size, flags} { } @@ -137,33 +137,33 @@ vm_area_guarded::~vm_area_guarded() {} uintptr_t vm_area_guarded::get_section() { - if (m_cache.count() > 0) { - return m_cache.pop(); - } + if (m_cache.count() > 0) { + return m_cache.pop(); + } - uintptr_t addr = m_next; - m_next += (m_pages + 1) * memory::frame_size; - return m_start + addr; + uintptr_t addr = m_next; + m_next += (m_pages + 1) * memory::frame_size; + return m_start + addr; } void vm_area_guarded::return_section(uintptr_t addr) { - m_cache.append(addr); + m_cache.append(addr); } bool vm_area_guarded::get_page(uintptr_t offset, uintptr_t &phys) { - if (offset > m_next) - return false; + if (offset > m_next) + return false; - // make sure this isn't in a guard page. (sections are - // m_pages big plus 1 leading guard page, so page 0 is - // invalid) - if ((offset >> 12) % (m_pages+1) == 0) - return false; + // make sure this isn't in a guard page. (sections are + // m_pages big plus 1 leading guard page, so page 0 is + // invalid) + if ((offset >> 12) % (m_pages+1) == 0) + return false; - return vm_area_untracked::get_page(offset, phys); + return vm_area_untracked::get_page(offset, phys); } diff --git a/src/kernel/objects/vm_area.h b/src/kernel/objects/vm_area.h index 7da6d8d..4d0ee56 100644 --- a/src/kernel/objects/vm_area.h +++ b/src/kernel/objects/vm_area.h @@ -20,158 +20,158 @@ enum class vm_flags : uint32_t #define VM_FLAG(name, v) name = v, #include "j6/tables/vm_flags.inc" #undef VM_FLAG - driver_mask = 0x000fffff, ///< flags allowed via syscall for drivers - user_mask = 0x0000ffff, ///< flags allowed via syscall for non-drivers + driver_mask = 0x000fffff, ///< flags allowed via syscall for drivers + user_mask = 0x0000ffff, ///< flags allowed via syscall for non-drivers }; /// Virtual memory areas allow control over memory allocation class vm_area : - public kobject + public kobject { public: - static constexpr kobject::type type = kobject::type::vma; + static constexpr kobject::type type = kobject::type::vma; - /// Constructor. - /// \arg size Initial virtual size of the memory area - /// \arg flags Flags for this memory area - vm_area(size_t size, vm_flags flags = vm_flags::none); + /// Constructor. + /// \arg size Initial virtual size of the memory area + /// \arg flags Flags for this memory area + vm_area(size_t size, vm_flags flags = vm_flags::none); - virtual ~vm_area(); + virtual ~vm_area(); - /// Get the current virtual size of the memory area - inline size_t size() const { return m_size; } + /// Get the current virtual size of the memory area + inline size_t size() const { return m_size; } - /// Get the flags set for this area - inline vm_flags flags() const { return m_flags; } + /// Get the flags set for this area + inline vm_flags flags() const { return m_flags; } - /// Track that this area was added to a vm_space - /// \arg space The space to add this area to - /// \returns False if this area cannot be added - virtual bool add_to(vm_space *space); + /// Track that this area was added to a vm_space + /// \arg space The space to add this area to + /// \returns False if this area cannot be added + virtual bool add_to(vm_space *space); - /// Track that this area was removed frm a vm_space - /// \arg space The space that is removing this area - /// \returns True if the removing space should free the pages - /// mapped for this area - virtual bool remove_from(vm_space *space); + /// Track that this area was removed frm a vm_space + /// \arg space The space that is removing this area + /// \returns True if the removing space should free the pages + /// mapped for this area + virtual bool remove_from(vm_space *space); - /// Change the virtual size of the memory area. This may cause - /// deallocation if the new size is smaller than the current size. - /// Note that if resizing is unsuccessful, the previous size will - /// be returned. - /// \arg size The desired new virtual size - /// \returns The new virtual size - virtual size_t resize(size_t size); + /// Change the virtual size of the memory area. This may cause + /// deallocation if the new size is smaller than the current size. + /// Note that if resizing is unsuccessful, the previous size will + /// be returned. + /// \arg size The desired new virtual size + /// \returns The new virtual size + virtual size_t resize(size_t size); - /// Get the physical page for the given offset - /// \arg offset The offset into the VMA - /// \arg phys [out] Receives the physical page address, if any - /// \returns True if there should be a page at the given offset - virtual bool get_page(uintptr_t offset, uintptr_t &phys) = 0; + /// Get the physical page for the given offset + /// \arg offset The offset into the VMA + /// \arg phys [out] Receives the physical page address, if any + /// \returns True if there should be a page at the given offset + virtual bool get_page(uintptr_t offset, uintptr_t &phys) = 0; protected: - virtual void on_no_handles() override; - bool can_resize(size_t size); + virtual void on_no_handles() override; + bool can_resize(size_t size); - size_t m_size; - vm_flags m_flags; - kutil::vector m_spaces; + size_t m_size; + vm_flags m_flags; + kutil::vector m_spaces; - // Initial static space for m_spaces - most areas will never grow - // beyond this size, so avoid allocations - static constexpr size_t static_size = 2; - vm_space *m_vector_static[static_size]; + // Initial static space for m_spaces - most areas will never grow + // beyond this size, so avoid allocations + static constexpr size_t static_size = 2; + vm_space *m_vector_static[static_size]; }; /// A shareable but non-allocatable memory area of contiguous physical /// addresses (like mmio) class vm_area_fixed : - public vm_area + public vm_area { public: - /// Constructor. - /// \arg start Starting physical address of this area - /// \arg size Size of the physical memory area - /// \arg flags Flags for this memory area - vm_area_fixed(uintptr_t start, size_t size, vm_flags flags = vm_flags::none); - virtual ~vm_area_fixed(); + /// Constructor. + /// \arg start Starting physical address of this area + /// \arg size Size of the physical memory area + /// \arg flags Flags for this memory area + vm_area_fixed(uintptr_t start, size_t size, vm_flags flags = vm_flags::none); + virtual ~vm_area_fixed(); - virtual size_t resize(size_t size) override; - virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; + virtual size_t resize(size_t size) override; + virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; private: - uintptr_t m_start; + uintptr_t m_start; }; /// Area that allows open allocation class vm_area_open : - public vm_area + public vm_area { public: - /// Constructor. - /// \arg size Initial virtual size of the memory area - /// \arg flags Flags for this memory area - vm_area_open(size_t size, vm_flags flags); - virtual ~vm_area_open(); + /// Constructor. + /// \arg size Initial virtual size of the memory area + /// \arg flags Flags for this memory area + vm_area_open(size_t size, vm_flags flags); + virtual ~vm_area_open(); - virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; + virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; private: - page_tree *m_mapped; + page_tree *m_mapped; }; /// Area that does not track its allocations and thus cannot be shared class vm_area_untracked : - public vm_area + public vm_area { public: - /// Constructor. - /// \arg size Initial virtual size of the memory area - /// \arg flags Flags for this memory area - vm_area_untracked(size_t size, vm_flags flags); - virtual ~vm_area_untracked(); + /// Constructor. + /// \arg size Initial virtual size of the memory area + /// \arg flags Flags for this memory area + vm_area_untracked(size_t size, vm_flags flags); + virtual ~vm_area_untracked(); - virtual bool add_to(vm_space *space) override; - virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; + virtual bool add_to(vm_space *space) override; + virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; }; /// Area split into standard-sized segments, separated by guard pages. /// Based on vm_area_untracked, can not be shared. class vm_area_guarded : - public vm_area_untracked + public vm_area_untracked { public: - /// Constructor. - /// \arg start Initial address where this area is mapped - /// \arg sec_pages Pages in an individual section - /// \arg size Initial virtual size of the memory area - /// \arg flags Flags for this memory area - vm_area_guarded( - uintptr_t start, - size_t sec_pages, - size_t size, - vm_flags flags); + /// Constructor. + /// \arg start Initial address where this area is mapped + /// \arg sec_pages Pages in an individual section + /// \arg size Initial virtual size of the memory area + /// \arg flags Flags for this memory area + vm_area_guarded( + uintptr_t start, + size_t sec_pages, + size_t size, + vm_flags flags); - virtual ~vm_area_guarded(); + virtual ~vm_area_guarded(); - /// Get an available section in this area - uintptr_t get_section(); + /// Get an available section in this area + uintptr_t get_section(); - /// Return a section address to the available pool - void return_section(uintptr_t addr); + /// Return a section address to the available pool + void return_section(uintptr_t addr); - virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; + virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; private: - kutil::vector m_cache; - uintptr_t m_start; - size_t m_pages; - uintptr_t m_next; + kutil::vector m_cache; + uintptr_t m_start; + size_t m_pages; + uintptr_t m_next; }; diff --git a/src/kernel/page_table.cpp b/src/kernel/page_table.cpp index 915493d..e3f07d4 100644 --- a/src/kernel/page_table.cpp +++ b/src/kernel/page_table.cpp @@ -14,21 +14,21 @@ constexpr size_t page_table::entry_sizes[4]; constexpr page_table::flag table_flags = - page_table::flag::present | - page_table::flag::write; + page_table::flag::present | + page_table::flag::write; page_table::iterator::iterator(uintptr_t virt, page_table *pml4) : - m_table {pml4, 0, 0, 0} + m_table {pml4, 0, 0, 0} { - for (unsigned i = 0; i < D; ++i) - m_index[i] = static_cast((virt >> (12 + 9*(3-i))) & 0x1ff); + for (unsigned i = 0; i < D; ++i) + m_index[i] = static_cast((virt >> (12 + 9*(3-i))) & 0x1ff); } page_table::iterator::iterator(const page_table::iterator &o) { - kutil::memcpy(&m_table, &o.m_table, sizeof(m_table)); - kutil::memcpy(&m_index, &o.m_index, sizeof(m_index)); + kutil::memcpy(&m_table, &o.m_table, sizeof(m_table)); + kutil::memcpy(&m_index, &o.m_index, sizeof(m_index)); } inline static level to_lv(unsigned i) { return static_cast(i); } @@ -37,136 +37,136 @@ inline static unsigned to_un(level i) { return static_cast(i); } uintptr_t page_table::iterator::start(level l) const { - uintptr_t address = 0; + uintptr_t address = 0; - for (level i = level::pml4; i <= l; ++i) - address |= static_cast(index(i)) << (12 + 9*(3-unsigned(i))); + for (level i = level::pml4; i <= l; ++i) + address |= static_cast(index(i)) << (12 + 9*(3-unsigned(i))); - // canonicalize the address - if (address & (1ull<<47)) - address |= (0xffffull<<48); + // canonicalize the address + if (address & (1ull<<47)) + address |= (0xffffull<<48); - return address; + return address; } uintptr_t page_table::iterator::end(level l) const { - kassert(l != level::pml4, "Called end() with level::pml4"); + kassert(l != level::pml4, "Called end() with level::pml4"); - uintptr_t address = 0; + uintptr_t address = 0; - for (level i = level::pml4; i < l; ++i) { - uintptr_t idx = index(i) + - ((i == l) ? 1 : 0); - address |= idx << (12 + 9*(3-unsigned(i))); - } + for (level i = level::pml4; i < l; ++i) { + uintptr_t idx = index(i) + + ((i == l) ? 1 : 0); + address |= idx << (12 + 9*(3-unsigned(i))); + } - // canonicalize the address - if (address & (1ull<<47)) - address |= (0xffffull<<48); + // canonicalize the address + if (address & (1ull<<47)) + address |= (0xffffull<<48); - return address; + return address; } level page_table::iterator::align() const { - for (int i = 4; i > 0; --i) - if (m_index[i-1]) return level(i); - return level::pml4; + for (int i = 4; i > 0; --i) + if (m_index[i-1]) return level(i); + return level::pml4; } page_table::level page_table::iterator::depth() const { - for (level i = level::pml4; i < level::page; ++i) - if (!(entry(i) & 1)) return i; - return level::pt; + for (level i = level::pml4; i < level::page; ++i) + if (!(entry(i) & 1)) return i; + return level::pt; } void page_table::iterator::next(level l) { - kassert(l != level::pml4, "Called next() with level::pml4"); - kassert(l <= level::page, "Called next() with too deep level"); + kassert(l != level::pml4, "Called next() with level::pml4"); + kassert(l <= level::page, "Called next() with too deep level"); - for (level i = l; i < level::page; ++i) - index(i) = 0; + for (level i = l; i < level::page; ++i) + index(i) = 0; - while (++index(--l) == 512) { - kassert(to_un(l), "iterator ran off the end of memory"); - index(l) = 0; - } + while (++index(--l) == 512) { + kassert(to_un(l), "iterator ran off the end of memory"); + index(l) = 0; + } } bool page_table::iterator::operator!=(const iterator &o) const { - for (unsigned i = 0; i < D; ++i) - if (o.m_index[i] != m_index[i]) - return true; + for (unsigned i = 0; i < D; ++i) + if (o.m_index[i] != m_index[i]) + return true; - return o.m_table[0] != m_table[0]; + return o.m_table[0] != m_table[0]; } bool page_table::iterator::check_table(level l) const { - // We're only dealing with D levels of paging, and - // there must always be a PML4. - if (l == level::pml4 || l > level::pt) - return l == level::pml4; + // We're only dealing with D levels of paging, and + // there must always be a PML4. + if (l == level::pml4 || l > level::pt) + return l == level::pml4; - uint64_t parent = entry(l - 1); - if (parent & 1) { - table(l) = reinterpret_cast(page_offset | (parent & ~0xfffull)); - return true; - } - return false; + uint64_t parent = entry(l - 1); + if (parent & 1) { + table(l) = reinterpret_cast(page_offset | (parent & ~0xfffull)); + return true; + } + return false; } void page_table::iterator::ensure_table(level l) { - // We're only dealing with D levels of paging, and - // there must always be a PML4. - if (l == level::pml4 || l > level::pt) return; - if (check_table(l)) return; + // We're only dealing with D levels of paging, and + // there must always be a PML4. + if (l == level::pml4 || l > level::pt) return; + if (check_table(l)) return; - page_table *table = page_table::get_table_page(); - uintptr_t phys = reinterpret_cast(table) & ~page_offset; + page_table *table = page_table::get_table_page(); + uintptr_t phys = reinterpret_cast(table) & ~page_offset; - uint64_t &parent = entry(l - 1); - flag flags = table_flags; - if (m_index[0] < memory::pml4e_kernel) - flags |= flag::user; + uint64_t &parent = entry(l - 1); + flag flags = table_flags; + if (m_index[0] < memory::pml4e_kernel) + flags |= flag::user; - m_table[unsigned(l)] = table; - parent = (phys & ~0xfffull) | flags; - __atomic_thread_fence(__ATOMIC_SEQ_CST); + m_table[unsigned(l)] = table; + parent = (phys & ~0xfffull) | flags; + __atomic_thread_fence(__ATOMIC_SEQ_CST); } page_table * page_table::get(int i, uint16_t *flags) const { - uint64_t entry = entries[i]; + uint64_t entry = entries[i]; - if ((entry & 0x1) == 0) - return nullptr; + if ((entry & 0x1) == 0) + return nullptr; - if (flags) - *flags = entry & 0xfffull; + if (flags) + *flags = entry & 0xfffull; - return reinterpret_cast((entry & ~0xfffull) + page_offset); + return reinterpret_cast((entry & ~0xfffull) + page_offset); } void page_table::set(int i, page_table *p, uint16_t flags) { - entries[i] = - (reinterpret_cast(p) - page_offset) | - (flags & 0xfff); + entries[i] = + (reinterpret_cast(p) - page_offset) | + (flags & 0xfff); } struct free_page_header { free_page_header *next; }; @@ -174,105 +174,105 @@ struct free_page_header { free_page_header *next; }; page_table * page_table::get_table_page() { - if (!s_cache_count) - fill_table_page_cache(); + if (!s_cache_count) + fill_table_page_cache(); - free_page_header *page = s_page_cache; - s_page_cache = s_page_cache->next; - --s_cache_count; + free_page_header *page = s_page_cache; + s_page_cache = s_page_cache->next; + --s_cache_count; - kutil::memset(page, 0, memory::frame_size); - return reinterpret_cast(page); + kutil::memset(page, 0, memory::frame_size); + return reinterpret_cast(page); } void page_table::free_table_page(page_table *pt) { - free_page_header *page = - reinterpret_cast(pt); - page->next = s_page_cache; - s_page_cache = page->next; - ++s_cache_count; + free_page_header *page = + reinterpret_cast(pt); + page->next = s_page_cache; + s_page_cache = page->next; + ++s_cache_count; } void page_table::fill_table_page_cache() { - constexpr size_t min_pages = 16; + constexpr size_t min_pages = 16; - frame_allocator &fa = frame_allocator::get(); - while (s_cache_count < min_pages) { - uintptr_t phys = 0; - size_t n = fa.allocate(min_pages - s_cache_count, &phys); + frame_allocator &fa = frame_allocator::get(); + while (s_cache_count < min_pages) { + uintptr_t phys = 0; + size_t n = fa.allocate(min_pages - s_cache_count, &phys); - free_page_header *start = - memory::to_virtual(phys); + free_page_header *start = + memory::to_virtual(phys); - for (int i = 0; i < n - 1; ++i) - kutil::offset_pointer(start, i * memory::frame_size) - ->next = kutil::offset_pointer(start, (i+1) * memory::frame_size); + for (int i = 0; i < n - 1; ++i) + kutil::offset_pointer(start, i * memory::frame_size) + ->next = kutil::offset_pointer(start, (i+1) * memory::frame_size); - free_page_header *end = - kutil::offset_pointer(start, (n-1) * memory::frame_size); + free_page_header *end = + kutil::offset_pointer(start, (n-1) * memory::frame_size); - end->next = s_page_cache; - s_page_cache = start; - s_cache_count += n; - } + end->next = s_page_cache; + s_page_cache = start; + s_cache_count += n; + } } void page_table::free(page_table::level l) { - unsigned last = l == level::pml4 - ? memory::pml4e_kernel - : memory::table_entries; + unsigned last = l == level::pml4 + ? memory::pml4e_kernel + : memory::table_entries; - frame_allocator &fa = frame_allocator::get(); - for (unsigned i = 0; i < last; ++i) { - if (!is_present(i)) continue; - if (is_page(l, i)) { - size_t count = memory::page_count(entry_sizes[unsigned(l)]); - fa.free(entries[i] & ~0xfffull, count); - } else { - get(i)->free(l + 1); - } - } + frame_allocator &fa = frame_allocator::get(); + for (unsigned i = 0; i < last; ++i) { + if (!is_present(i)) continue; + if (is_page(l, i)) { + size_t count = memory::page_count(entry_sizes[unsigned(l)]); + fa.free(entries[i] & ~0xfffull, count); + } else { + get(i)->free(l + 1); + } + } - free_table_page(this); + free_table_page(this); } void page_table::dump(page_table::level lvl, bool recurse) { - console *cons = console::get(); + console *cons = console::get(); - cons->printf("\nLevel %d page table @ %lx:\n", lvl, this); - for (int i=0; iprintf("\nLevel %d page table @ %lx:\n", lvl, this); + for (int i=0; iprintf(" %3d: %016lx NOT PRESENT\n", i, ent); + if ((ent & 0x1) == 0) + cons->printf(" %3d: %016lx NOT PRESENT\n", i, ent); - else if ((lvl == level::pdp || lvl == level::pd) && (ent & 0x80) == 0x80) - cons->printf(" %3d: %016lx -> Large page at %016lx\n", i, ent, ent & ~0xfffull); + else if ((lvl == level::pdp || lvl == level::pd) && (ent & 0x80) == 0x80) + cons->printf(" %3d: %016lx -> Large page at %016lx\n", i, ent, ent & ~0xfffull); - else if (lvl == level::pt) - cons->printf(" %3d: %016lx -> Page at %016lx\n", i, ent, ent & ~0xfffull); + else if (lvl == level::pt) + cons->printf(" %3d: %016lx -> Page at %016lx\n", i, ent, ent & ~0xfffull); - else - cons->printf(" %3d: %016lx -> Level %d table at %016lx\n", - i, ent, deeper(lvl), (ent & ~0xfffull) + page_offset); - } + else + cons->printf(" %3d: %016lx -> Level %d table at %016lx\n", + i, ent, deeper(lvl), (ent & ~0xfffull) + page_offset); + } - if (lvl != level::pt && recurse) { - for (int i=0; i<=memory::table_entries; ++i) { - if (is_large_page(lvl, i)) - continue; + if (lvl != level::pt && recurse) { + for (int i=0; i<=memory::table_entries; ++i) { + if (is_large_page(lvl, i)) + continue; - page_table *next = get(i); - if (next) - next->dump(deeper(lvl), true); - } - } + page_table *next = get(i); + if (next) + next->dump(deeper(lvl), true); + } + } } diff --git a/src/kernel/page_table.h b/src/kernel/page_table.h index 9dcecfc..267a299 100644 --- a/src/kernel/page_table.h +++ b/src/kernel/page_table.h @@ -11,184 +11,184 @@ struct free_page_header; /// Struct to allow easy accessing of a memory page being used as a page table. struct page_table { - /// Enum representing the table levels in 4-level paging - enum class level : unsigned { pml4, pdp, pd, pt, page }; + /// Enum representing the table levels in 4-level paging + enum class level : unsigned { pml4, pdp, pd, pt, page }; - /// Page entry flags - enum class flag : uint64_t - { - none = 0x0000, - present = 0x0001, /// Entry is present in the table - write = 0x0002, /// Section may be written - user = 0x0004, /// User-accessible - pat0 = 0x0008, /// PAT selector bit 0 - pat1 = 0x0010, /// PAT selector bit 1 - accessed = 0x0020, /// Entry has been accessed - dirty = 0x0040, /// Page has been written to - page = 0x0080, /// Entry is a large page - pat2 = 0x0080, /// PAT selector bit 2 on PT entries - global = 0x0100, /// Entry is not PCID-specific - pat2_lg = 0x1000, /// PAT selector bit 2 on large/huge pages + /// Page entry flags + enum class flag : uint64_t + { + none = 0x0000, + present = 0x0001, /// Entry is present in the table + write = 0x0002, /// Section may be written + user = 0x0004, /// User-accessible + pat0 = 0x0008, /// PAT selector bit 0 + pat1 = 0x0010, /// PAT selector bit 1 + accessed = 0x0020, /// Entry has been accessed + dirty = 0x0040, /// Page has been written to + page = 0x0080, /// Entry is a large page + pat2 = 0x0080, /// PAT selector bit 2 on PT entries + global = 0x0100, /// Entry is not PCID-specific + pat2_lg = 0x1000, /// PAT selector bit 2 on large/huge pages - wb = none, - wt = pat0, - uc_ = pat1, - uc = pat0 | pat1, - wc = pat0 | pat1 | pat2, - wc_lg = pat0 | pat1 | pat2_lg, - }; + wb = none, + wt = pat0, + uc_ = pat1, + uc = pat0 | pat1, + wc = pat0 | pat1 | pat2, + wc_lg = pat0 | pat1 | pat2_lg, + }; - /// Helper for getting the next level value - inline static level deeper(level l) { - return static_cast(static_cast(l) + 1); - } + /// Helper for getting the next level value + inline static level deeper(level l) { + return static_cast(static_cast(l) + 1); + } - static constexpr size_t entry_sizes[] = { - 0x8000000000, // PML4 entry: 512 GiB - 0x40000000, // PDP entry: 1 GiB - 0x200000, // PD entry: 2 MiB - 0x1000}; // PT entry: 4 KiB + static constexpr size_t entry_sizes[] = { + 0x8000000000, // PML4 entry: 512 GiB + 0x40000000, // PDP entry: 1 GiB + 0x200000, // PD entry: 2 MiB + 0x1000}; // PT entry: 4 KiB - /// Iterator over page table entries. - class iterator - { - /// The number of levels - static constexpr unsigned D = 4; + /// Iterator over page table entries. + class iterator + { + /// The number of levels + static constexpr unsigned D = 4; - public: - /// Constructor. - /// \arg virt Virtual address this iterator is starting at - /// \arg pml4 Root of the page tables to iterate - iterator(uintptr_t virt, page_table *pml4); + public: + /// Constructor. + /// \arg virt Virtual address this iterator is starting at + /// \arg pml4 Root of the page tables to iterate + iterator(uintptr_t virt, page_table *pml4); - /// Copy constructor. - iterator(const iterator &o); + /// Copy constructor. + iterator(const iterator &o); - /// Get the starting address of pages mapped by the current table - /// of level l. - uintptr_t start(level l) const; + /// Get the starting address of pages mapped by the current table + /// of level l. + uintptr_t start(level l) const; - /// Get the ending address of pages mapped by the current table - /// of level l. - uintptr_t end(level l) const; + /// Get the ending address of pages mapped by the current table + /// of level l. + uintptr_t end(level l) const; - /// Get the widest table type the current address is aligned to - level align() const; + /// Get the widest table type the current address is aligned to + level align() const; - /// Get the current virtual address - inline uintptr_t vaddress() const { return start(level::pt); } + /// Get the current virtual address + inline uintptr_t vaddress() const { return start(level::pt); } - /// Get the nth page table of the current address - inline page_table *& table(level l) const { return m_table[unsigned(l)]; } + /// Get the nth page table of the current address + inline page_table *& table(level l) const { return m_table[unsigned(l)]; } - /// Get the index in the nth page table of the current address - inline uint16_t & index(level l) { return m_index[unsigned(l)]; } + /// Get the index in the nth page table of the current address + inline uint16_t & index(level l) { return m_index[unsigned(l)]; } - /// Get the index in the nth page table of the current address - inline uint16_t index(level l) const { return m_index[unsigned(l)]; } + /// Get the index in the nth page table of the current address + inline uint16_t index(level l) const { return m_index[unsigned(l)]; } - /// Get the current table entry of the table at the given level. - inline uint64_t entry(level l) const { - for (unsigned i = 1; i <= unsigned(l); ++i) - if (!check_table(level(i))) return 0; - return table(l)->entries[index(l)]; - } + /// Get the current table entry of the table at the given level. + inline uint64_t entry(level l) const { + for (unsigned i = 1; i <= unsigned(l); ++i) + if (!check_table(level(i))) return 0; + return table(l)->entries[index(l)]; + } - /// Get a *non-const* reference to the current table entry of - /// the table at the given level. - inline uint64_t & entry(level l) { - for (unsigned i = 1; i <= unsigned(l); ++i) ensure_table(level(i)); - return table(l)->entries[index(l)]; - } + /// Get a *non-const* reference to the current table entry of + /// the table at the given level. + inline uint64_t & entry(level l) { + for (unsigned i = 1; i <= unsigned(l); ++i) ensure_table(level(i)); + return table(l)->entries[index(l)]; + } - /// Get the depth of tables that actually exist for the current address - level depth() const; + /// Get the depth of tables that actually exist for the current address + level depth() const; - /// Increment iteration to the next entry aligned to the given level - void next(level l); + /// Increment iteration to the next entry aligned to the given level + void next(level l); - /// Increment iteration to the next entry at the deepest level - inline void increment() { next(level::page); } + /// Increment iteration to the next entry at the deepest level + inline void increment() { next(level::page); } - inline uint64_t & operator*() { return entry(level::pt); } - inline iterator & operator++() { increment(); return *this; } - inline iterator operator++(int) { iterator old {*this}; increment(); return old; } + inline uint64_t & operator*() { return entry(level::pt); } + inline iterator & operator++() { increment(); return *this; } + inline iterator operator++(int) { iterator old {*this}; increment(); return old; } - bool operator!=(const iterator &o) const; + bool operator!=(const iterator &o) const; - bool check_table(level l) const; - void ensure_table(level l); + bool check_table(level l) const; + void ensure_table(level l); - private: - // The table array is mutable because we might update it with existing - // tables; a 'view switch'. therefore, be careful not to modify table - // contents in const functions. - mutable page_table *m_table[D]; - uint16_t m_index[D]; - }; + private: + // The table array is mutable because we might update it with existing + // tables; a 'view switch'. therefore, be careful not to modify table + // contents in const functions. + mutable page_table *m_table[D]; + uint16_t m_index[D]; + }; - /// Allocate a page for a page table, or pull one from the cache - /// \returns An empty page, mapped in the linear offset area - static page_table * get_table_page(); + /// Allocate a page for a page table, or pull one from the cache + /// \returns An empty page, mapped in the linear offset area + static page_table * get_table_page(); - /// Return a page table's page to the page cache. - /// \arg pt The page to be returned - static void free_table_page(page_table *pt); + /// Return a page table's page to the page cache. + /// \arg pt The page to be returned + static void free_table_page(page_table *pt); - // Ensure the page table page cache has a minimum number of pages - // in it. - static void fill_table_page_cache(); + // Ensure the page table page cache has a minimum number of pages + // in it. + static void fill_table_page_cache(); - static free_page_header *s_page_cache; ///< Cache of free pages to use for tables - static size_t s_cache_count; ///< Number of pages in s_page_cache + static free_page_header *s_page_cache; ///< Cache of free pages to use for tables + static size_t s_cache_count; ///< Number of pages in s_page_cache - /// Get an entry in the page table as a page_table pointer - /// \arg i Index of the entry in this page table - /// \arg flags [out] If set, this will receive the entry's flags - /// \returns The corresponding entry, offset into page-offset memory - page_table * get(int i, uint16_t *flags = nullptr) const; + /// Get an entry in the page table as a page_table pointer + /// \arg i Index of the entry in this page table + /// \arg flags [out] If set, this will receive the entry's flags + /// \returns The corresponding entry, offset into page-offset memory + page_table * get(int i, uint16_t *flags = nullptr) const; - /// Set an entry in the page table as a page_table pointer - /// \arg i Index of the entry in this page table - /// \arg flags The flags for the entry - void set(int i, page_table *p, uint16_t flags); + /// Set an entry in the page table as a page_table pointer + /// \arg i Index of the entry in this page table + /// \arg flags The flags for the entry + void set(int i, page_table *p, uint16_t flags); - /// Check if the given entry represents a large or huge page - inline bool is_large_page(level l, int i) const { - return (l == level::pdp || l == level::pd) && (entries[i] & 0x80) == 0x80; - } + /// Check if the given entry represents a large or huge page + inline bool is_large_page(level l, int i) const { + return (l == level::pdp || l == level::pd) && (entries[i] & 0x80) == 0x80; + } - /// Check if the given entry is marked as present in the table - inline bool is_present(int i) const { return (entries[i] & 0x1) == 0x1; } + /// Check if the given entry is marked as present in the table + inline bool is_present(int i) const { return (entries[i] & 0x1) == 0x1; } - /// Check if the given entry represents a page (of any size) - inline bool is_page(level l, int i) const { return (l == level::pt) || is_large_page(l, i); } + /// Check if the given entry represents a page (of any size) + inline bool is_page(level l, int i) const { return (l == level::pt) || is_large_page(l, i); } - /// Free this page table and all resources it references - /// \arg l The level of this page table - void free(level l); + /// Free this page table and all resources it references + /// \arg l The level of this page table + void free(level l); - /// Print this table to the debug console. - void dump(level lvl = level::pml4, bool recurse = true); + /// Print this table to the debug console. + void dump(level lvl = level::pml4, bool recurse = true); - uint64_t entries[memory::table_entries]; + uint64_t entries[memory::table_entries]; }; inline page_table::level operator+(page_table::level a, unsigned b) { - return static_cast(static_cast(a) + b); + return static_cast(static_cast(a) + b); } inline page_table::level operator-(page_table::level a, unsigned b) { - return static_cast(static_cast(a) - b); + return static_cast(static_cast(a) - b); } inline bool operator>(page_table::level a, page_table::level b) { - return static_cast(a) > static_cast(b); + return static_cast(a) > static_cast(b); } inline bool operator<(page_table::level a, page_table::level b) { - return static_cast(a) < static_cast(b); + return static_cast(a) < static_cast(b); } inline page_table::level& operator++(page_table::level& l) { l = l + 1; return l; } diff --git a/src/kernel/page_tree.cpp b/src/kernel/page_tree.cpp index 7a9b47b..cfe1964 100644 --- a/src/kernel/page_tree.cpp +++ b/src/kernel/page_tree.cpp @@ -19,134 +19,134 @@ static constexpr unsigned max_level = 5; static constexpr unsigned bits_per_level = 6; inline uint64_t to_word(uint64_t base, uint64_t level, uint64_t flags = 0) { - // Clear out the non-appropriate bits for this level - base &= (~0x3full << (level*bits_per_level)); + // Clear out the non-appropriate bits for this level + base &= (~0x3full << (level*bits_per_level)); - return - (base & 0x3ffffffffff) | - ((level & 0x7) << 42) | - ((flags & 0x7ffff) << 45); + return + (base & 0x3ffffffffff) | + ((level & 0x7) << 42) | + ((flags & 0x7ffff) << 45); } inline uint64_t to_base(uint64_t word) { - return word & 0x3ffffffffff; + return word & 0x3ffffffffff; } inline uint64_t to_level(uint64_t word) { - return (word >> 42) & 0x3f; + return (word >> 42) & 0x3f; } inline uint64_t to_flags(uint64_t word) { - return (word >> 45); + return (word >> 45); } inline bool contains(uint64_t page_off, uint64_t word, uint8_t &index) { - uint64_t base = to_base(word); - uint64_t bits = to_level(word) * bits_per_level; - index = (page_off >> bits) & 0x3f; - return (page_off & (~0x3full << bits)) == base; + uint64_t base = to_base(word); + uint64_t bits = to_level(word) * bits_per_level; + index = (page_off >> bits) & 0x3f; + return (page_off & (~0x3full << bits)) == base; } inline uint64_t index_for(uint64_t page_off, uint8_t level) { - return (page_off >> (level*bits_per_level)) & 0x3f; + return (page_off >> (level*bits_per_level)) & 0x3f; } page_tree::page_tree(uint64_t base, uint8_t level) : - m_base {to_word(base, level)} + m_base {to_word(base, level)} { - kutil::memset(m_entries, 0, sizeof(m_entries)); + kutil::memset(m_entries, 0, sizeof(m_entries)); } bool page_tree::find(const page_tree *root, uint64_t offset, uintptr_t &page) { - uint64_t page_off = offset >> 12; // change to pagewise offset - page_tree const *node = root; - while (node) { - uint8_t level = to_level(node->m_base); - uint8_t index = 0; - if (!contains(page_off, node->m_base, index)) - return false; + uint64_t page_off = offset >> 12; // change to pagewise offset + page_tree const *node = root; + while (node) { + uint8_t level = to_level(node->m_base); + uint8_t index = 0; + if (!contains(page_off, node->m_base, index)) + return false; - if (!level) { - uintptr_t entry = node->m_entries[index].entry; - page = entry & ~1ull; // bit 0 marks 'present' - return (entry & 1); - } + if (!level) { + uintptr_t entry = node->m_entries[index].entry; + page = entry & ~1ull; // bit 0 marks 'present' + return (entry & 1); + } - node = node->m_entries[index].child; - } + node = node->m_entries[index].child; + } - return false; + return false; } bool page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page) { - uint64_t page_off = offset >> 12; // change to pagewise offset - page_tree *level0 = nullptr; + uint64_t page_off = offset >> 12; // change to pagewise offset + page_tree *level0 = nullptr; - if (!root) { - // There's no root yet, just make a level0 and make it - // the root. - level0 = new page_tree(page_off, 0); - root = level0; - } else { - // Find or insert an existing level0 - page_tree **parent = &root; - page_tree *node = root; - uint8_t parent_level = max_level + 1; + if (!root) { + // There's no root yet, just make a level0 and make it + // the root. + level0 = new page_tree(page_off, 0); + root = level0; + } else { + // Find or insert an existing level0 + page_tree **parent = &root; + page_tree *node = root; + uint8_t parent_level = max_level + 1; - while (node) { - uint8_t level = to_level(node->m_base); - uint8_t index = 0; - if (!contains(page_off, node->m_base, index)) { - // We found a valid parent but the slot where this node should - // go contains another node. Insert an intermediate parent of - // this node and a new level0 into the parent. - uint64_t other = to_base(node->m_base); - uint8_t lcl = parent_level; - while (index_for(page_off, lcl) == index_for(other, lcl)) - --lcl; + while (node) { + uint8_t level = to_level(node->m_base); + uint8_t index = 0; + if (!contains(page_off, node->m_base, index)) { + // We found a valid parent but the slot where this node should + // go contains another node. Insert an intermediate parent of + // this node and a new level0 into the parent. + uint64_t other = to_base(node->m_base); + uint8_t lcl = parent_level; + while (index_for(page_off, lcl) == index_for(other, lcl)) + --lcl; - page_tree *inter = new page_tree(page_off, lcl); - inter->m_entries[index_for(other, lcl)].child = node; - *parent = inter; + page_tree *inter = new page_tree(page_off, lcl); + inter->m_entries[index_for(other, lcl)].child = node; + *parent = inter; - level0 = new page_tree(page_off, 0); - inter->m_entries[index_for(page_off, lcl)].child = level0; - break; - } + level0 = new page_tree(page_off, 0); + inter->m_entries[index_for(page_off, lcl)].child = level0; + break; + } - if (!level) { - level0 = node; - break; - } + if (!level) { + level0 = node; + break; + } - parent = &node->m_entries[index].child; - node = *parent; - } + parent = &node->m_entries[index].child; + node = *parent; + } - kassert( node || parent, "Both node and parent were null in find_or_add"); + kassert( node || parent, "Both node and parent were null in find_or_add"); - if (!node) { - // We found a parent with an empty spot where this node should - // be. Insert a new level0 there. - level0 = new page_tree(page_off, 0); - *parent = level0; - } - } + if (!node) { + // We found a parent with an empty spot where this node should + // be. Insert a new level0 there. + level0 = new page_tree(page_off, 0); + *parent = level0; + } + } - kassert(level0, "Got through find_or_add without a level0"); - uint8_t index = index_for(page_off, 0); - uint64_t &ent = level0->m_entries[index].entry; - if (!(ent & 1)) { - // No entry for this page exists, so make one - if (!frame_allocator::get().allocate(1, &ent)) - return false; - ent |= 1; - } + kassert(level0, "Got through find_or_add without a level0"); + uint8_t index = index_for(page_off, 0); + uint64_t &ent = level0->m_entries[index].entry; + if (!(ent & 1)) { + // No entry for this page exists, so make one + if (!frame_allocator::get().allocate(1, &ent)) + return false; + ent |= 1; + } - page = ent & ~0xfffull; - return true; + page = ent & ~0xfffull; + return true; } diff --git a/src/kernel/page_tree.h b/src/kernel/page_tree.h index 45d2a5d..98e0a08 100644 --- a/src/kernel/page_tree.h +++ b/src/kernel/page_tree.h @@ -8,32 +8,32 @@ class page_tree { public: - /// Get the physical address of the page at the given offset. - /// \arg root The root node of the tree - /// \arg offset Offset into the VMA, in bytes - /// \arg page [out] Receives the page physical address, if found - /// \returns True if a page was found - static bool find(const page_tree *root, uint64_t offset, uintptr_t &page); + /// Get the physical address of the page at the given offset. + /// \arg root The root node of the tree + /// \arg offset Offset into the VMA, in bytes + /// \arg page [out] Receives the page physical address, if found + /// \returns True if a page was found + static bool find(const page_tree *root, uint64_t offset, uintptr_t &page); - /// Get the physical address of the page at the given offset. If one does - /// not exist yet, allocate a page, insert it, and return that. - /// \arg root [inout] The root node of the tree. This pointer may be updated. - /// \arg offset Offset into the VMA, in bytes - /// \arg page [out] Receives the page physical address, if found - /// \returns True if a page was found - static bool find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page); + /// Get the physical address of the page at the given offset. If one does + /// not exist yet, allocate a page, insert it, and return that. + /// \arg root [inout] The root node of the tree. This pointer may be updated. + /// \arg offset Offset into the VMA, in bytes + /// \arg page [out] Receives the page physical address, if found + /// \returns True if a page was found + static bool find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page); private: - page_tree(uint64_t base, uint8_t level); + page_tree(uint64_t base, uint8_t level); - /// Stores the page offset of the start of this node's pages in bits 0:41 - /// and the depth of tree this node represents in bits 42:44 (0-7) - uint64_t m_base; + /// Stores the page offset of the start of this node's pages in bits 0:41 + /// and the depth of tree this node represents in bits 42:44 (0-7) + uint64_t m_base; - /// For a level 0 node, the entries area all physical page addresses. - /// Other nodes contain pointers to child tree nodes. - union { - uintptr_t entry; - page_tree *child; - } m_entries[64]; + /// For a level 0 node, the entries area all physical page addresses. + /// Other nodes contain pointers to child tree nodes. + union { + uintptr_t entry; + page_tree *child; + } m_entries[64]; }; diff --git a/src/kernel/panic.serial/display.h b/src/kernel/panic.serial/display.h index fe2f73c..c5c646a 100644 --- a/src/kernel/panic.serial/display.h +++ b/src/kernel/panic.serial/display.h @@ -13,8 +13,8 @@ class symbol_table; struct frame { - frame *prev; - uintptr_t return_addr; + frame *prev; + uintptr_t return_addr; }; void print_header(serial_port &out, const char *message); diff --git a/src/kernel/panic.serial/main.cpp b/src/kernel/panic.serial/main.cpp index ba36c18..df4cefd 100644 --- a/src/kernel/panic.serial/main.cpp +++ b/src/kernel/panic.serial/main.cpp @@ -14,7 +14,7 @@ void panic_handler( panic::symbol_table syms(symbol_data); panic::frame const *fp = nullptr; - asm ( "mov %%rbp, %0" : "=r" (fp) ); + asm ( "mov %%rbp, %0" : "=r" (fp) ); print_header(com1, message); print_callstack(com1, syms, fp); diff --git a/src/kernel/panic.serial/serial.cpp b/src/kernel/panic.serial/serial.cpp index ed575d3..34a2579 100644 --- a/src/kernel/panic.serial/serial.cpp +++ b/src/kernel/panic.serial/serial.cpp @@ -21,22 +21,22 @@ inline void outb(uint16_t port, uint8_t val) { } inline uint8_t inb(uint16_t port) { - uint8_t val; - asm ( "inb %1, %0" : "=a"(val) : "Nd"(port) ); - return val; + uint8_t val; + asm ( "inb %1, %0" : "=a"(val) : "Nd"(port) ); + return val; } serial_port::serial_port(uint16_t port) : - m_port(port) + m_port(port) { - outb(port + IER, 0x00); // Disable all interrupts - outb(port + LCR, 0x80); // Enable the Divisor Latch Access Bit - outb(port + DLL, 0x01); // Divisor low byte: 1 (115200 baud) - outb(port + DLH, 0x00); // Divisor high byte - outb(port + LCR, 0x03); // 8-N-1, diable DLAB - outb(port + FCR, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger - outb(port + MCR, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable) + outb(port + IER, 0x00); // Disable all interrupts + outb(port + LCR, 0x80); // Enable the Divisor Latch Access Bit + outb(port + DLL, 0x01); // Divisor low byte: 1 (115200 baud) + outb(port + DLH, 0x00); // Divisor high byte + outb(port + LCR, 0x03); // 8-N-1, diable DLAB + outb(port + FCR, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger + outb(port + MCR, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable) } inline bool read_ready(uint16_t port) { return (inb(port + LSR) & 0x01) != 0; } diff --git a/src/kernel/panic.serial/serial.h b/src/kernel/panic.serial/serial.h index 653b579..9aa1a6b 100644 --- a/src/kernel/panic.serial/serial.h +++ b/src/kernel/panic.serial/serial.h @@ -8,14 +8,14 @@ namespace panic { class serial_port { public: - /// Constructor. - /// \arg port The IO address of the serial port - serial_port(uint16_t port); + /// Constructor. + /// \arg port The IO address of the serial port + serial_port(uint16_t port); - void write(const char *s); + void write(const char *s); private: - uint16_t m_port; + uint16_t m_port; }; constexpr uint16_t COM1 = 0x03f8; diff --git a/src/kernel/panic.serial/symbol_table.cpp b/src/kernel/panic.serial/symbol_table.cpp index 00d0977..89d2f38 100644 --- a/src/kernel/panic.serial/symbol_table.cpp +++ b/src/kernel/panic.serial/symbol_table.cpp @@ -16,13 +16,13 @@ symbol_table::symbol_table(const void *data) : const char * symbol_table::find_symbol(uintptr_t addr) const { - // TODO: binary search - for (auto &e : m_entries) { - if (addr >= e.address && addr < e.address + e.size) + // TODO: binary search + for (auto &e : m_entries) { + if (addr >= e.address && addr < e.address + e.size) return reinterpret_cast(m_data) + e.name; - } + } - return nullptr; + return nullptr; } } // namespace panic diff --git a/src/kernel/panic.serial/symbol_table.h b/src/kernel/panic.serial/symbol_table.h index 3abc66f..3188237 100644 --- a/src/kernel/panic.serial/symbol_table.h +++ b/src/kernel/panic.serial/symbol_table.h @@ -8,22 +8,22 @@ namespace panic { class symbol_table { public: - /// Constructor. - /// \arg data Pointer to the start of the symbol_table data. - symbol_table(const void *data); + /// Constructor. + /// \arg data Pointer to the start of the symbol_table data. + symbol_table(const void *data); - /// Find the name of the symbol at the given address - /// \args addr Address to search for - /// \returns Name of the symbol if found, or null - const char * find_symbol(uintptr_t addr) const; + /// Find the name of the symbol at the given address + /// \args addr Address to search for + /// \returns Name of the symbol if found, or null + const char * find_symbol(uintptr_t addr) const; private: - struct entry - { - uintptr_t address; + struct entry + { + uintptr_t address; size_t size; - uintptr_t name; - }; + uintptr_t name; + }; const void *m_data; counted m_entries; diff --git a/src/kernel/pci.cpp b/src/kernel/pci.cpp index 7327999..a5676f1 100644 --- a/src/kernel/pci.cpp +++ b/src/kernel/pci.cpp @@ -6,174 +6,174 @@ struct pci_cap_msi { - pci_cap::type id; - uint8_t next; - uint16_t control; + pci_cap::type id; + uint8_t next; + uint16_t control; } __attribute__ ((packed)); struct pci_cap_msi32 { - pci_cap::type id; - uint8_t next; - uint16_t control; - uint32_t address; - uint16_t data; - uint16_t reserved; - uint32_t mask; - uint32_t pending; + pci_cap::type id; + uint8_t next; + uint16_t control; + uint32_t address; + uint16_t data; + uint16_t reserved; + uint32_t mask; + uint32_t pending; } __attribute__ ((packed)); struct pci_cap_msi64 { - pci_cap::type id; - uint8_t next; - uint16_t control; - uint64_t address; - uint16_t data; - uint16_t reserved; - uint32_t mask; - uint32_t pending; + pci_cap::type id; + uint8_t next; + uint16_t control; + uint64_t address; + uint16_t data; + uint16_t reserved; + uint32_t mask; + uint32_t pending; } __attribute__ ((packed)); void dump_msi(pci_cap_msi *cap) { - auto cons = console::get(); - cons->printf("MSI Cap:\n"); - cons->printf(" id: %02x\n", cap->id); - cons->printf(" next: %02x\n", cap->next); - cons->printf("control: %04x\n", cap->control); - if (cap->control & 0x0080) { - pci_cap_msi64 *cap64 = reinterpret_cast(cap); - cons->printf("address: %016x\n", cap64->address); - cons->printf(" data: %04x\n", cap64->data); - if (cap->control & 0x100) { - cons->printf(" mask: %08x\n", cap64->mask); - cons->printf("pending: %08x\n", cap64->pending); - } - } else { - pci_cap_msi32 *cap32 = reinterpret_cast(cap); - cons->printf("address: %08x\n", cap32->address); - cons->printf(" data: %04x\n", cap32->data); - if (cap->control & 0x100) { - cons->printf(" mask: %08x\n", cap32->mask); - cons->printf("pending: %08x\n", cap32->pending); - } - } - cons->putc('\n'); + auto cons = console::get(); + cons->printf("MSI Cap:\n"); + cons->printf(" id: %02x\n", cap->id); + cons->printf(" next: %02x\n", cap->next); + cons->printf("control: %04x\n", cap->control); + if (cap->control & 0x0080) { + pci_cap_msi64 *cap64 = reinterpret_cast(cap); + cons->printf("address: %016x\n", cap64->address); + cons->printf(" data: %04x\n", cap64->data); + if (cap->control & 0x100) { + cons->printf(" mask: %08x\n", cap64->mask); + cons->printf("pending: %08x\n", cap64->pending); + } + } else { + pci_cap_msi32 *cap32 = reinterpret_cast(cap); + cons->printf("address: %08x\n", cap32->address); + cons->printf(" data: %04x\n", cap32->data); + if (cap->control & 0x100) { + cons->printf(" mask: %08x\n", cap32->mask); + cons->printf("pending: %08x\n", cap32->pending); + } + } + cons->putc('\n'); }; pci_device::pci_device() : - m_base(nullptr), - m_bus_addr(0), - m_vendor(0), - m_device(0), - m_class(0), - m_subclass(0), - m_progif(0), - m_revision(0), - m_irq(isr::isrIgnoreF), - m_header_type(0) + m_base(nullptr), + m_bus_addr(0), + m_vendor(0), + m_device(0), + m_class(0), + m_subclass(0), + m_progif(0), + m_revision(0), + m_irq(isr::isrIgnoreF), + m_header_type(0) { } pci_device::pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t func) : - m_base(group.base_for(bus, device, func)), - m_msi(nullptr), - m_bus_addr(bus_addr(bus, device, func)), - m_irq(isr::isrIgnoreF) + m_base(group.base_for(bus, device, func)), + m_msi(nullptr), + m_bus_addr(bus_addr(bus, device, func)), + m_irq(isr::isrIgnoreF) { - m_vendor = m_base[0] & 0xffff; - m_device = (m_base[0] >> 16) & 0xffff; + m_vendor = m_base[0] & 0xffff; + m_device = (m_base[0] >> 16) & 0xffff; - m_revision = m_base[2] & 0xff; - m_progif = (m_base[2] >> 8) & 0xff; - m_subclass = (m_base[2] >> 16) & 0xff; - m_class = (m_base[2] >> 24) & 0xff; + m_revision = m_base[2] & 0xff; + m_progif = (m_base[2] >> 8) & 0xff; + m_subclass = (m_base[2] >> 16) & 0xff; + m_class = (m_base[2] >> 24) & 0xff; - m_header_type = (m_base[3] >> 16) & 0x7f; - m_multi = ((m_base[3] >> 16) & 0x80) == 0x80; + m_header_type = (m_base[3] >> 16) & 0x7f; + m_multi = ((m_base[3] >> 16) & 0x80) == 0x80; - uint16_t *command = reinterpret_cast(&m_base[1]); - *command |= 0x400; // Mask old INTx style interrupts + uint16_t *command = reinterpret_cast(&m_base[1]); + *command |= 0x400; // Mask old INTx style interrupts - uint16_t *status = command + 1; + uint16_t *status = command + 1; - log::info(logs::device, "Found PCIe device at %02d:%02d:%d of type %x.%x.%x id %04x:%04x", - bus, device, func, m_class, m_subclass, m_progif, m_vendor, m_device); + log::info(logs::device, "Found PCIe device at %02d:%02d:%d of type %x.%x.%x id %04x:%04x", + bus, device, func, m_class, m_subclass, m_progif, m_vendor, m_device); - if (*status & 0x0010) { - // Walk the extended capabilities list - uint8_t next = m_base[13] & 0xff; - while (next) { - pci_cap *cap = reinterpret_cast(kutil::offset_pointer(m_base, next)); - next = cap->next; - log::debug(logs::device, " - found PCI cap type %02x", cap->id); + if (*status & 0x0010) { + // Walk the extended capabilities list + uint8_t next = m_base[13] & 0xff; + while (next) { + pci_cap *cap = reinterpret_cast(kutil::offset_pointer(m_base, next)); + next = cap->next; + log::debug(logs::device, " - found PCI cap type %02x", cap->id); - if (cap->id == pci_cap::type::msi) { - m_msi = cap; - pci_cap_msi *mcap = reinterpret_cast(cap); - mcap->control &= ~0x70; // at most 1 vector allocated - mcap->control |= 0x01; // Enable interrupts, at most 1 vector allocated - } - } - } + if (cap->id == pci_cap::type::msi) { + m_msi = cap; + pci_cap_msi *mcap = reinterpret_cast(cap); + mcap->control &= ~0x70; // at most 1 vector allocated + mcap->control |= 0x01; // Enable interrupts, at most 1 vector allocated + } + } + } } uint32_t pci_device::get_bar(unsigned i) { - if (m_header_type == 0) { - kassert(i < 6, "Requested BAR >5 for PCI device"); - } else if (m_header_type == 1) { - kassert(i < 2, "Requested BAR >1 for PCI bridge"); - } else { - kassert(0, "Requested BAR for other PCI device type"); - } + if (m_header_type == 0) { + kassert(i < 6, "Requested BAR >5 for PCI device"); + } else if (m_header_type == 1) { + kassert(i < 2, "Requested BAR >1 for PCI bridge"); + } else { + kassert(0, "Requested BAR for other PCI device type"); + } - return m_base[4+i]; + return m_base[4+i]; } void pci_device::set_bar(unsigned i, uint32_t val) { - if (m_header_type == 0) { - kassert(i < 6, "Requested BAR >5 for PCI device"); - } else if (m_header_type == 1) { - kassert(i < 2, "Requested BAR >1 for PCI bridge"); - } else { - kassert(0, "Requested BAR for other PCI device type"); - } + if (m_header_type == 0) { + kassert(i < 6, "Requested BAR >5 for PCI device"); + } else if (m_header_type == 1) { + kassert(i < 2, "Requested BAR >1 for PCI bridge"); + } else { + kassert(0, "Requested BAR for other PCI device type"); + } - m_base[4+i] = val; + m_base[4+i] = val; } void pci_device::write_msi_regs(uintptr_t address, uint16_t data) { - kassert(m_msi, "Tried to write MSI for a device without that cap"); - if (m_msi->id == pci_cap::type::msi) { - pci_cap_msi *mcap = reinterpret_cast(m_msi); - if (mcap->control & 0x0080) { - pci_cap_msi64 *mcap64 = reinterpret_cast(m_msi); - mcap64->address = address; - mcap64->data = data; - } else { - pci_cap_msi32 *mcap32 = reinterpret_cast(m_msi); - mcap32->address = address; - mcap32->data = data; - } - uint16_t control = mcap->control; - control &= 0xff8f; // We're allocating one vector, clear 6::4 - control |= 0x0001; // Enable MSI - mcap->control = control; - } else { - kassert(0, "MIS-X is NYI"); - } + kassert(m_msi, "Tried to write MSI for a device without that cap"); + if (m_msi->id == pci_cap::type::msi) { + pci_cap_msi *mcap = reinterpret_cast(m_msi); + if (mcap->control & 0x0080) { + pci_cap_msi64 *mcap64 = reinterpret_cast(m_msi); + mcap64->address = address; + mcap64->data = data; + } else { + pci_cap_msi32 *mcap32 = reinterpret_cast(m_msi); + mcap32->address = address; + mcap32->data = data; + } + uint16_t control = mcap->control; + control &= 0xff8f; // We're allocating one vector, clear 6::4 + control |= 0x0001; // Enable MSI + mcap->control = control; + } else { + kassert(0, "MIS-X is NYI"); + } } bool pci_group::has_device(uint8_t bus, uint8_t device, uint8_t func) { - return (*base_for(bus, device, func) & 0xffff) != 0xffff; + return (*base_for(bus, device, func) & 0xffff) != 0xffff; } diff --git a/src/kernel/pci.h b/src/kernel/pci.h index c54d9a7..06b8228 100644 --- a/src/kernel/pci.h +++ b/src/kernel/pci.h @@ -10,14 +10,14 @@ enum class isr : uint8_t; struct pci_cap { - enum class type : uint8_t - { - msi = 0x05, - msix = 0x11 - }; + enum class type : uint8_t + { + msi = 0x05, + msix = 0x11 + }; - type id; - uint8_t next; + type id; + uint8_t next; } __attribute__ ((packed)); @@ -25,117 +25,117 @@ struct pci_cap class pci_device { public: - /// Default constructor creates an empty object. - pci_device(); + /// Default constructor creates an empty object. + pci_device(); - /// Constructor - /// \arg group The group of this device's bus - /// \arg bus The bus number this device is on - /// \arg device The device number of this device - /// \arg func The function number of this device - pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t func); + /// Constructor + /// \arg group The group of this device's bus + /// \arg bus The bus number this device is on + /// \arg device The device number of this device + /// \arg func The function number of this device + pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t func); - /// Check if this device is multi-function. - /// \returns True if this device is multi-function - inline bool multi() const { return m_multi; } + /// Check if this device is multi-function. + /// \returns True if this device is multi-function + inline bool multi() const { return m_multi; } - /// Get the bus number this device is on. - /// \returns The bus number - inline uint8_t bus() const { return (m_bus_addr >> 8); } + /// Get the bus number this device is on. + /// \returns The bus number + inline uint8_t bus() const { return (m_bus_addr >> 8); } - /// Get the device number of this device on its bus - /// \returns The device number - inline uint8_t device() const { return (m_bus_addr >> 3) & 0x1f; } + /// Get the device number of this device on its bus + /// \returns The device number + inline uint8_t device() const { return (m_bus_addr >> 3) & 0x1f; } - /// Get the function number of this device on its device - /// \returns The function number - inline uint8_t function() const { return m_bus_addr & 0x7; } + /// Get the function number of this device on its device + /// \returns The function number + inline uint8_t function() const { return m_bus_addr & 0x7; } - /// Get the device class - /// \returns The PCI device class - inline uint8_t devclass() const { return m_class; } + /// Get the device class + /// \returns The PCI device class + inline uint8_t devclass() const { return m_class; } - /// Get the device subclass - /// \returns The PCI device subclass - inline uint8_t subclass() const { return m_subclass; } + /// Get the device subclass + /// \returns The PCI device subclass + inline uint8_t subclass() const { return m_subclass; } - /// Get the device program interface - /// \returns The PCI device program interface - inline uint8_t progif() const { return m_progif; } + /// Get the device program interface + /// \returns The PCI device program interface + inline uint8_t progif() const { return m_progif; } - /// Read one of the device's Base Address Registers - /// \arg i Which BAR to read (up to 5 for non-bridges) - /// \returns The contents of the BAR - uint32_t get_bar(unsigned i); + /// Read one of the device's Base Address Registers + /// \arg i Which BAR to read (up to 5 for non-bridges) + /// \returns The contents of the BAR + uint32_t get_bar(unsigned i); - /// Write one of the device's Base Address Registers - /// \arg i Which BAR to read (up to 5 for non-bridges) - /// \arg val The value to write - void set_bar(unsigned i, uint32_t val); + /// Write one of the device's Base Address Registers + /// \arg i Which BAR to read (up to 5 for non-bridges) + /// \arg val The value to write + void set_bar(unsigned i, uint32_t val); - /// Write to the MSI registers - /// \arg addr The address to write to the MSI address registers - /// \arg data The value to write to the MSI data register - void write_msi_regs(uintptr_t addr, uint16_t data); + /// Write to the MSI registers + /// \arg addr The address to write to the MSI address registers + /// \arg data The value to write to the MSI data register + void write_msi_regs(uintptr_t addr, uint16_t data); - /// Get a bus address, given the bus/device/function numbers. - /// \arg bus Number of the bus - /// \arg device Index of the device on the bus - /// \arg func The function number within the device - /// \returns The computed bus_addr - static inline uint16_t bus_addr(uint8_t bus, uint8_t device, uint8_t func) - { - return bus << 8 | device << 3 | func; - } + /// Get a bus address, given the bus/device/function numbers. + /// \arg bus Number of the bus + /// \arg device Index of the device on the bus + /// \arg func The function number within the device + /// \returns The computed bus_addr + static inline uint16_t bus_addr(uint8_t bus, uint8_t device, uint8_t func) + { + return bus << 8 | device << 3 | func; + } private: - uint32_t *m_base; - pci_cap *m_msi; + uint32_t *m_base; + pci_cap *m_msi; - /// Bus address: 15:8 bus, 7:3 device, 2:0 device - uint16_t m_bus_addr; + /// Bus address: 15:8 bus, 7:3 device, 2:0 device + uint16_t m_bus_addr; - uint16_t m_vendor; - uint16_t m_device; + uint16_t m_vendor; + uint16_t m_device; - uint8_t m_class; - uint8_t m_subclass; - uint8_t m_progif; - uint8_t m_revision; - bool m_multi; + uint8_t m_class; + uint8_t m_subclass; + uint8_t m_progif; + uint8_t m_revision; + bool m_multi; - // Might as well cache these to fill out the struct align - isr m_irq; - uint8_t m_header_type; + // Might as well cache these to fill out the struct align + isr m_irq; + uint8_t m_header_type; }; /// Represents data about a PCI bus group from the ACPI MCFG struct pci_group { - uint16_t group; - uint16_t bus_start; - uint16_t bus_end; + uint16_t group; + uint16_t bus_start; + uint16_t bus_end; - uint32_t *base; + uint32_t *base; - /// Get the base address of the MMIO configuration registers for a device - /// \arg bus The bus number of the device (relative to this group) - /// \arg device The device number on the given bus - /// \arg func The function number on the device - /// \returns A pointer to the memory-mapped configuration registers - inline uint32_t * base_for(uint8_t bus, uint8_t device, uint8_t func) - { - return kutil::offset_pointer(base, - pci_device::bus_addr(bus, device, func) << 12); - } + /// Get the base address of the MMIO configuration registers for a device + /// \arg bus The bus number of the device (relative to this group) + /// \arg device The device number on the given bus + /// \arg func The function number on the device + /// \returns A pointer to the memory-mapped configuration registers + inline uint32_t * base_for(uint8_t bus, uint8_t device, uint8_t func) + { + return kutil::offset_pointer(base, + pci_device::bus_addr(bus, device, func) << 12); + } - /// Check if the given device function is present. - /// \arg bus The bus number of the device (relative to this group) - /// \arg device The device number on the given bus - /// \arg func The function number on the device - /// \returns True if the device function is present - bool has_device(uint8_t bus, uint8_t device, uint8_t func); + /// Check if the given device function is present. + /// \arg bus The bus number of the device (relative to this group) + /// \arg device The device number on the given bus + /// \arg func The function number on the device + /// \returns True if the device function is present + bool has_device(uint8_t bus, uint8_t device, uint8_t func); }; diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index 065c5ae..592cc31 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -31,304 +31,304 @@ scheduler *scheduler::s_instance = nullptr; struct run_queue { - tcb_node *current = nullptr; - tcb_list ready[scheduler::num_priorities]; - tcb_list blocked; + tcb_node *current = nullptr; + tcb_list ready[scheduler::num_priorities]; + tcb_list blocked; - uint64_t last_promotion = 0; - uint64_t last_steal = 0; - kutil::spinlock lock; + uint64_t last_promotion = 0; + uint64_t last_steal = 0; + kutil::spinlock lock; }; scheduler::scheduler(unsigned cpus) : - m_next_pid {1}, - m_clock {0} + m_next_pid {1}, + m_clock {0} { - kassert(!s_instance, "Created multiple schedulers!"); - if (!s_instance) - s_instance = this; + kassert(!s_instance, "Created multiple schedulers!"); + if (!s_instance) + s_instance = this; - m_run_queues.set_size(cpus); + m_run_queues.set_size(cpus); } scheduler::~scheduler() { - // Not truly necessary - if the scheduler is going away, the whole - // system is probably going down. But let's be clean. - if (s_instance == this) - s_instance = nullptr; + // Not truly necessary - if the scheduler is going away, the whole + // system is probably going down. But let's be clean. + if (s_instance == this) + s_instance = nullptr; } template inline T * push(uintptr_t &rsp, size_t size = sizeof(T)) { - rsp -= size; - T *p = reinterpret_cast(rsp); - rsp &= ~(sizeof(uint64_t)-1); // Align the stack - return p; + rsp -= size; + T *p = reinterpret_cast(rsp); + rsp &= ~(sizeof(uint64_t)-1); // Align the stack + return p; } void scheduler::create_kernel_task(void (*task)(), uint8_t priority, bool constant) { - thread *th = process::kernel_process().create_thread(priority, false); - auto *tcb = th->tcb(); + thread *th = process::kernel_process().create_thread(priority, false); + auto *tcb = th->tcb(); - th->add_thunk_kernel(reinterpret_cast(task)); + th->add_thunk_kernel(reinterpret_cast(task)); - tcb->time_left = quantum(priority); - if (constant) - th->set_state(thread::state::constant); + tcb->time_left = quantum(priority); + if (constant) + th->set_state(thread::state::constant); - th->set_state(thread::state::ready); + th->set_state(thread::state::ready); - log::debug(logs::task, "Creating kernel task: thread %llx pri %d", th->koid(), tcb->priority); - log::debug(logs::task, " RSP0 %016lx", tcb->rsp0); - log::debug(logs::task, " RSP %016lx", tcb->rsp); - log::debug(logs::task, " PML4 %016lx", tcb->pml4); + log::debug(logs::task, "Creating kernel task: thread %llx pri %d", th->koid(), tcb->priority); + log::debug(logs::task, " RSP0 %016lx", tcb->rsp0); + log::debug(logs::task, " RSP %016lx", tcb->rsp); + log::debug(logs::task, " PML4 %016lx", tcb->pml4); } uint32_t scheduler::quantum(int priority) { - return quantum_micros << priority; + return quantum_micros << priority; } void scheduler::start() { - cpu_data &cpu = current_cpu(); - run_queue &queue = m_run_queues[cpu.index]; + cpu_data &cpu = current_cpu(); + run_queue &queue = m_run_queues[cpu.index]; - { - kutil::scoped_lock lock {queue.lock}; + { + kutil::scoped_lock lock {queue.lock}; - process *kp = &process::kernel_process(); - thread *idle = thread::create_idle_thread(*kp, max_priority, cpu.rsp0); + process *kp = &process::kernel_process(); + thread *idle = thread::create_idle_thread(*kp, max_priority, cpu.rsp0); - auto *tcb = idle->tcb(); - cpu.process = kp; - cpu.thread = idle; - cpu.tcb = tcb; + auto *tcb = idle->tcb(); + cpu.process = kp; + cpu.thread = idle; + cpu.tcb = tcb; - queue.current = tcb; - } + queue.current = tcb; + } - cpu.apic->enable_timer(isr::isrTimer, false); - cpu.apic->reset_timer(10); + cpu.apic->enable_timer(isr::isrTimer, false); + cpu.apic->reset_timer(10); } void scheduler::add_thread(TCB *t) { - cpu_data &cpu = current_cpu(); - run_queue &queue = m_run_queues[cpu.index]; - kutil::scoped_lock lock {queue.lock}; + cpu_data &cpu = current_cpu(); + run_queue &queue = m_run_queues[cpu.index]; + kutil::scoped_lock lock {queue.lock}; - queue.blocked.push_back(static_cast(t)); - t->time_left = quantum(t->priority); + queue.blocked.push_back(static_cast(t)); + t->time_left = quantum(t->priority); } void scheduler::prune(run_queue &queue, uint64_t now) { - // Find processes that are ready or have exited and - // move them to the appropriate lists. - auto *tcb = queue.blocked.front(); - while (tcb) { - thread *th = thread::from_tcb(tcb); - uint8_t priority = tcb->priority; + // Find processes that are ready or have exited and + // move them to the appropriate lists. + auto *tcb = queue.blocked.front(); + while (tcb) { + thread *th = thread::from_tcb(tcb); + uint8_t priority = tcb->priority; - bool ready = th->has_state(thread::state::ready); - bool exited = th->has_state(thread::state::exited); - bool constant = th->has_state(thread::state::constant); - bool current = tcb == queue.current; + bool ready = th->has_state(thread::state::ready); + bool exited = th->has_state(thread::state::exited); + bool constant = th->has_state(thread::state::constant); + bool current = tcb == queue.current; - ready |= th->wake_on_time(now); + ready |= th->wake_on_time(now); - auto *remove = tcb; - tcb = tcb->next(); - if (!exited && !ready) - continue; + auto *remove = tcb; + tcb = tcb->next(); + if (!exited && !ready) + continue; - if (exited) { - // If the current thread has exited, wait until the next call - // to prune() to delete it, because we may be deleting our current - // page tables - if (current) continue; + if (exited) { + // If the current thread has exited, wait until the next call + // to prune() to delete it, because we may be deleting our current + // page tables + if (current) continue; - queue.blocked.remove(remove); - process &p = th->parent(); + queue.blocked.remove(remove); + process &p = th->parent(); - // thread_exited deletes the thread, and returns true if the process - // should also now be deleted - if(!current && p.thread_exited(th)) - delete &p; - } else { - queue.blocked.remove(remove); - log::debug(logs::sched, "Prune: readying unblocked thread %llx", th->koid()); - queue.ready[remove->priority].push_back(remove); - } - } + // thread_exited deletes the thread, and returns true if the process + // should also now be deleted + if(!current && p.thread_exited(th)) + delete &p; + } else { + queue.blocked.remove(remove); + log::debug(logs::sched, "Prune: readying unblocked thread %llx", th->koid()); + queue.ready[remove->priority].push_back(remove); + } + } } void scheduler::check_promotions(run_queue &queue, uint64_t now) { - for (auto &pri_list : queue.ready) { - for (auto *tcb : pri_list) { - const thread *th = thread::from_tcb(queue.current); - const bool constant = th->has_state(thread::state::constant); - if (constant) - continue; + for (auto &pri_list : queue.ready) { + for (auto *tcb : pri_list) { + const thread *th = thread::from_tcb(queue.current); + const bool constant = th->has_state(thread::state::constant); + if (constant) + continue; - const uint64_t age = now - tcb->last_ran; - const uint8_t priority = tcb->priority; + const uint64_t age = now - tcb->last_ran; + const uint8_t priority = tcb->priority; - bool stale = - age > quantum(priority) * 2 && - tcb->priority > promote_limit && - !constant; + bool stale = + age > quantum(priority) * 2 && + tcb->priority > promote_limit && + !constant; - if (stale) { - // If the thread is stale, promote it - queue.ready[priority].remove(tcb); - tcb->priority -= 1; - tcb->time_left = quantum(tcb->priority); - queue.ready[tcb->priority].push_back(tcb); - log::info(logs::sched, "Scheduler promoting thread %llx, priority %d", - th->koid(), tcb->priority); - } - } - } + if (stale) { + // If the thread is stale, promote it + queue.ready[priority].remove(tcb); + tcb->priority -= 1; + tcb->time_left = quantum(tcb->priority); + queue.ready[tcb->priority].push_back(tcb); + log::info(logs::sched, "Scheduler promoting thread %llx, priority %d", + th->koid(), tcb->priority); + } + } + } - queue.last_promotion = now; + queue.last_promotion = now; } static size_t balance_lists(tcb_list &to, tcb_list &from) { - size_t to_len = to.length(); - size_t from_len = from.length(); + size_t to_len = to.length(); + size_t from_len = from.length(); - // Only steal from the rich, don't be Dennis Moore - if (from_len <= to_len) - return 0; + // Only steal from the rich, don't be Dennis Moore + if (from_len <= to_len) + return 0; - size_t steal = (from_len - to_len) / 2; - for (size_t i = 0; i < steal; ++i) - to.push_front(from.pop_front()); - return steal; + size_t steal = (from_len - to_len) / 2; + for (size_t i = 0; i < steal; ++i) + to.push_front(from.pop_front()); + return steal; } void scheduler::steal_work(cpu_data &cpu) { - // Lock this cpu's queue for the whole time while we modify it - run_queue &my_queue = m_run_queues[cpu.index]; - kutil::scoped_lock my_queue_lock {my_queue.lock}; + // Lock this cpu's queue for the whole time while we modify it + run_queue &my_queue = m_run_queues[cpu.index]; + kutil::scoped_lock my_queue_lock {my_queue.lock}; - const unsigned count = m_run_queues.count(); - for (unsigned i = 0; i < count; ++i) { - if (i == cpu.index) continue; + const unsigned count = m_run_queues.count(); + for (unsigned i = 0; i < count; ++i) { + if (i == cpu.index) continue; - run_queue &other_queue = m_run_queues[i]; - kutil::scoped_lock other_queue_lock {other_queue.lock}; + run_queue &other_queue = m_run_queues[i]; + kutil::scoped_lock other_queue_lock {other_queue.lock}; - size_t stolen = 0; + size_t stolen = 0; - // Don't steal from max_priority, that's the idle thread - for (unsigned pri = 0; pri < max_priority; ++pri) - stolen += balance_lists(my_queue.ready[pri], other_queue.ready[pri]); + // Don't steal from max_priority, that's the idle thread + for (unsigned pri = 0; pri < max_priority; ++pri) + stolen += balance_lists(my_queue.ready[pri], other_queue.ready[pri]); - stolen += balance_lists(my_queue.blocked, other_queue.blocked); + stolen += balance_lists(my_queue.blocked, other_queue.blocked); - if (stolen) - log::debug(logs::sched, "CPU%02x stole %2d tasks from CPU%02x", - cpu.index, stolen, i); - } + if (stolen) + log::debug(logs::sched, "CPU%02x stole %2d tasks from CPU%02x", + cpu.index, stolen, i); + } } void scheduler::schedule() { - cpu_data &cpu = current_cpu(); - run_queue &queue = m_run_queues[cpu.index]; - lapic &apic = *cpu.apic; - uint32_t remaining = apic.stop_timer(); + cpu_data &cpu = current_cpu(); + run_queue &queue = m_run_queues[cpu.index]; + lapic &apic = *cpu.apic; + uint32_t remaining = apic.stop_timer(); - // Only one CPU can be stealing at a time - if (m_steal_turn == cpu.index && - m_clock - queue.last_steal > steal_frequency) { - steal_work(cpu); - queue.last_steal = m_clock; - m_steal_turn = (m_steal_turn + 1) % m_run_queues.count(); - } + // Only one CPU can be stealing at a time + if (m_steal_turn == cpu.index && + m_clock - queue.last_steal > steal_frequency) { + steal_work(cpu); + queue.last_steal = m_clock; + m_steal_turn = (m_steal_turn + 1) % m_run_queues.count(); + } - // We need to explicitly lock/unlock here instead of - // using a scoped lock, because the scope doesn't "end" - // for the current thread until it gets scheduled again - kutil::spinlock::waiter waiter; - queue.lock.acquire(&waiter); + // We need to explicitly lock/unlock here instead of + // using a scoped lock, because the scope doesn't "end" + // for the current thread until it gets scheduled again + kutil::spinlock::waiter waiter; + queue.lock.acquire(&waiter); - queue.current->time_left = remaining; - thread *th = thread::from_tcb(queue.current); - uint8_t priority = queue.current->priority; - const bool constant = th->has_state(thread::state::constant); + queue.current->time_left = remaining; + thread *th = thread::from_tcb(queue.current); + uint8_t priority = queue.current->priority; + const bool constant = th->has_state(thread::state::constant); - if (remaining == 0) { - if (priority < max_priority && !constant) { - // Process used its whole timeslice, demote it - ++queue.current->priority; - log::debug(logs::sched, "Scheduler demoting thread %llx, priority %d", - th->koid(), queue.current->priority); - } - queue.current->time_left = quantum(queue.current->priority); - } else if (remaining > 0) { - // Process gave up CPU, give it a small bonus to its - // remaining timeslice. - uint32_t bonus = quantum(priority) >> 4; - queue.current->time_left += bonus; - } + if (remaining == 0) { + if (priority < max_priority && !constant) { + // Process used its whole timeslice, demote it + ++queue.current->priority; + log::debug(logs::sched, "Scheduler demoting thread %llx, priority %d", + th->koid(), queue.current->priority); + } + queue.current->time_left = quantum(queue.current->priority); + } else if (remaining > 0) { + // Process gave up CPU, give it a small bonus to its + // remaining timeslice. + uint32_t bonus = quantum(priority) >> 4; + queue.current->time_left += bonus; + } - if (th->has_state(thread::state::ready)) { - queue.ready[queue.current->priority].push_back(queue.current); - } else { - queue.blocked.push_back(queue.current); - } + if (th->has_state(thread::state::ready)) { + queue.ready[queue.current->priority].push_back(queue.current); + } else { + queue.blocked.push_back(queue.current); + } - clock::get().update(); - prune(queue, ++m_clock); - if (m_clock - queue.last_promotion > promote_frequency) - check_promotions(queue, m_clock); + clock::get().update(); + prune(queue, ++m_clock); + if (m_clock - queue.last_promotion > promote_frequency) + check_promotions(queue, m_clock); - priority = 0; - while (queue.ready[priority].empty()) { - ++priority; - kassert(priority < num_priorities, "All runlists are empty"); - } + priority = 0; + while (queue.ready[priority].empty()) { + ++priority; + kassert(priority < num_priorities, "All runlists are empty"); + } - queue.current->last_ran = m_clock; + queue.current->last_ran = m_clock; - auto *next = queue.ready[priority].pop_front(); - next->last_ran = m_clock; - apic.reset_timer(next->time_left); + auto *next = queue.ready[priority].pop_front(); + next->last_ran = m_clock; + apic.reset_timer(next->time_left); - if (next == queue.current) { - queue.lock.release(&waiter); - return; - } + if (next == queue.current) { + queue.lock.release(&waiter); + return; + } - thread *next_thread = thread::from_tcb(next); + thread *next_thread = thread::from_tcb(next); - cpu.thread = next_thread; - cpu.process = &next_thread->parent(); - queue.current = next; + cpu.thread = next_thread; + cpu.process = &next_thread->parent(); + queue.current = next; - log::debug(logs::sched, "CPU%02x switching threads %llx->%llx", - cpu.index, th->koid(), next_thread->koid()); - log::debug(logs::sched, " priority %d time left %d @ %lld.", - next->priority, next->time_left, m_clock); - log::debug(logs::sched, " PML4 %llx", next->pml4); + log::debug(logs::sched, "CPU%02x switching threads %llx->%llx", + cpu.index, th->koid(), next_thread->koid()); + log::debug(logs::sched, " priority %d time left %d @ %lld.", + next->priority, next->time_left, m_clock); + log::debug(logs::sched, " PML4 %llx", next->pml4); - queue.lock.release(&waiter); - task_switch(queue.current); + queue.lock.release(&waiter); + task_switch(queue.current); } diff --git a/src/kernel/scheduler.h b/src/kernel/scheduler.h index f8b19a0..02674a1 100644 --- a/src/kernel/scheduler.h +++ b/src/kernel/scheduler.h @@ -8,7 +8,7 @@ namespace kernel { namespace args { - struct program; + struct program; }} struct cpu_data; @@ -22,82 +22,82 @@ struct run_queue; class scheduler { public: - /// Total number of priority levels - static const uint8_t num_priorities = 8; + /// Total number of priority levels + static const uint8_t num_priorities = 8; - /// Maximum (least urgent/interactive) priority - static const uint8_t max_priority = num_priorities - 1; + /// Maximum (least urgent/interactive) priority + static const uint8_t max_priority = num_priorities - 1; - /// Default priority on process creation - static const uint8_t default_priority = 1; + /// Default priority on process creation + static const uint8_t default_priority = 1; - /// Lowest (most urgent) priority achieved via promotion - static const uint8_t promote_limit = 1; + /// Lowest (most urgent) priority achieved via promotion + static const uint8_t promote_limit = 1; - /// How long the base timer quantum is, in us - static const uint64_t quantum_micros = 500; + /// How long the base timer quantum is, in us + static const uint64_t quantum_micros = 500; - /// How many quanta a process gets before being rescheduled - static const uint16_t process_quanta = 10; + /// How many quanta a process gets before being rescheduled + static const uint16_t process_quanta = 10; - /// Constructor. - /// \arg cpus The number of CPUs to schedule for - scheduler(unsigned cpus); - ~scheduler(); + /// Constructor. + /// \arg cpus The number of CPUs to schedule for + scheduler(unsigned cpus); + ~scheduler(); - /// Create a new process from a program image in memory. - /// \arg program The descriptor of the pogram in memory - /// \returns The main thread of the loaded process - thread * load_process(kernel::args::program &program); + /// Create a new process from a program image in memory. + /// \arg program The descriptor of the pogram in memory + /// \returns The main thread of the loaded process + thread * load_process(kernel::args::program &program); - /// Create a new kernel task - /// \arg proc Function to run as a kernel task - /// \arg priority Priority to start the process with - /// \arg constant True if this task cannot be promoted/demoted - void create_kernel_task( - void (*task)(), - uint8_t priority, - bool constant = false); + /// Create a new kernel task + /// \arg proc Function to run as a kernel task + /// \arg priority Priority to start the process with + /// \arg constant True if this task cannot be promoted/demoted + void create_kernel_task( + void (*task)(), + uint8_t priority, + bool constant = false); - /// Get the quantum for a given priority. - static uint32_t quantum(int priority); + /// Get the quantum for a given priority. + static uint32_t quantum(int priority); - /// Start the scheduler working. This may involve starting - /// timer interrupts or other preemption methods. - void start(); + /// Start the scheduler working. This may involve starting + /// timer interrupts or other preemption methods. + void start(); - /// Run the scheduler, possibly switching to a new task - void schedule(); + /// Run the scheduler, possibly switching to a new task + void schedule(); - /// Start scheduling a new thread. - /// \arg t The new thread's TCB - void add_thread(TCB *t); + /// Start scheduling a new thread. + /// \arg t The new thread's TCB + void add_thread(TCB *t); - /// Get a reference to the scheduler - /// \returns A reference to the global system scheduler - static scheduler & get() { return *s_instance; } + /// Get a reference to the scheduler + /// \returns A reference to the global system scheduler + static scheduler & get() { return *s_instance; } private: - friend class process; + friend class process; - static constexpr uint64_t promote_frequency = 10; - static constexpr uint64_t steal_frequency = 10; + static constexpr uint64_t promote_frequency = 10; + static constexpr uint64_t steal_frequency = 10; - void prune(run_queue &queue, uint64_t now); - void check_promotions(run_queue &queue, uint64_t now); - void steal_work(cpu_data &cpu); + void prune(run_queue &queue, uint64_t now); + void check_promotions(run_queue &queue, uint64_t now); + void steal_work(cpu_data &cpu); - uint32_t m_next_pid; - uint32_t m_tick_count; + uint32_t m_next_pid; + uint32_t m_tick_count; - process *m_kernel_process; + process *m_kernel_process; - kutil::vector m_run_queues; + kutil::vector m_run_queues; - // TODO: lol a real clock - uint64_t m_clock = 0; + // TODO: lol a real clock + uint64_t m_clock = 0; - unsigned m_steal_turn = 0; - static scheduler *s_instance; + unsigned m_steal_turn = 0; + static scheduler *s_instance; }; diff --git a/src/kernel/serial.cpp b/src/kernel/serial.cpp index a639034..9d247bc 100644 --- a/src/kernel/serial.cpp +++ b/src/kernel/serial.cpp @@ -31,28 +31,28 @@ uint8_t com1_out_buffer[4096*4]; uint8_t com1_in_buffer[512]; serial_port::serial_port() : - m_writing(false), - m_port(0) + m_writing(false), + m_port(0) { } serial_port::serial_port(uint16_t port) : - m_writing(false), - m_port(port), - m_out_buffer(com1_out_buffer, sizeof(com1_out_buffer)), - m_in_buffer(com1_in_buffer, sizeof(com1_in_buffer)) + m_writing(false), + m_port(port), + m_out_buffer(com1_out_buffer, sizeof(com1_out_buffer)), + m_in_buffer(com1_in_buffer, sizeof(com1_in_buffer)) { - outb(port + IER, 0x00); // Disable all interrupts - outb(port + LCR, 0x80); // Enable the Divisor Latch Access Bit - outb(port + DLL, 0x01); // Divisor low byte: 1 (115200 baud) - outb(port + DLH, 0x00); // Divisor high byte - outb(port + LCR, 0x03); // 8-N-1, diable DLAB - outb(port + FCR, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger - outb(port + MCR, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable) - outb(port + IER, 0x03); // Enable interrupts + outb(port + IER, 0x00); // Disable all interrupts + outb(port + LCR, 0x80); // Enable the Divisor Latch Access Bit + outb(port + DLL, 0x01); // Divisor low byte: 1 (115200 baud) + outb(port + DLH, 0x00); // Divisor high byte + outb(port + LCR, 0x03); // 8-N-1, diable DLAB + outb(port + FCR, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger + outb(port + MCR, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable) + outb(port + IER, 0x03); // Enable interrupts - // Clear out pending interrupts - handle_interrupt(); + // Clear out pending interrupts + handle_interrupt(); } inline bool read_ready(uint16_t port) { return (inb(port + LSR) & 0x01) != 0; } @@ -61,102 +61,102 @@ inline bool write_ready(uint16_t port) { return (inb(port + LSR) & 0x20) != 0; } void serial_port::handle_interrupt() { - interrupts_disable(); - uint8_t iir = inb(m_port + IIR); + interrupts_disable(); + uint8_t iir = inb(m_port + IIR); - while ((iir & 1) == 0) { - uint8_t reg = 0; - switch ((iir>>1) & 0x3) { - case 0: // Modem status change - reg = inb(m_port + MSR); - handle_error(MSR, reg); - break; + while ((iir & 1) == 0) { + uint8_t reg = 0; + switch ((iir>>1) & 0x3) { + case 0: // Modem status change + reg = inb(m_port + MSR); + handle_error(MSR, reg); + break; - case 1: // Transmit buffer empty - do_write(); - break; + case 1: // Transmit buffer empty + do_write(); + break; - case 2: // Received data available - do_read(); - break; + case 2: // Received data available + do_read(); + break; - case 3: // Line status change - reg = inb(m_port + LSR); - handle_error(LSR, reg); - break; - } + case 3: // Line status change + reg = inb(m_port + LSR); + handle_error(LSR, reg); + break; + } - iir = inb(m_port + IIR); - } - interrupts_enable(); + iir = inb(m_port + IIR); + } + interrupts_enable(); } void serial_port::do_read() { - size_t used = 0; - uint8_t *data = nullptr; - size_t avail = m_in_buffer.reserve(fifo_size, reinterpret_cast(&data)); + size_t used = 0; + uint8_t *data = nullptr; + size_t avail = m_in_buffer.reserve(fifo_size, reinterpret_cast(&data)); - while (used < avail && read_ready(m_port)) { - *data++ = inb(m_port); - used++; - } + while (used < avail && read_ready(m_port)) { + *data++ = inb(m_port); + used++; + } - m_in_buffer.commit(used); + m_in_buffer.commit(used); } void serial_port::do_write() { - uint8_t *data = nullptr; - uint8_t tmp[fifo_size]; + uint8_t *data = nullptr; + uint8_t tmp[fifo_size]; - size_t n = m_out_buffer.get_block(reinterpret_cast(&data)); + size_t n = m_out_buffer.get_block(reinterpret_cast(&data)); - m_writing = (n > 0); - if (!m_writing) - return; + m_writing = (n > 0); + if (!m_writing) + return; - if (n > fifo_size) - n = fifo_size; + if (n > fifo_size) + n = fifo_size; - kutil::memcpy(tmp, data, n); - m_out_buffer.consume(n); + kutil::memcpy(tmp, data, n); + m_out_buffer.consume(n); - for (size_t i = 0; i < n; ++i) - outb(m_port, data[i]); + for (size_t i = 0; i < n; ++i) + outb(m_port, data[i]); } void serial_port::handle_error(uint16_t reg, uint8_t value) { - kassert(false, "serial line error"); + kassert(false, "serial line error"); } char serial_port::read() { - uint8_t *data = nullptr; - size_t n = m_in_buffer.get_block(reinterpret_cast(&data)); - if (!n) return 0; - char c = *data; - m_in_buffer.consume(1); - return c; + uint8_t *data = nullptr; + size_t n = m_in_buffer.get_block(reinterpret_cast(&data)); + if (!n) return 0; + char c = *data; + m_in_buffer.consume(1); + return c; } void serial_port::write(char c) { - uint8_t *data = nullptr; - size_t avail = m_out_buffer.reserve(1, reinterpret_cast(&data)); - if (!avail) - return; - *data = c; - m_out_buffer.commit(1); + uint8_t *data = nullptr; + size_t avail = m_out_buffer.reserve(1, reinterpret_cast(&data)); + if (!avail) + return; + *data = c; + m_out_buffer.commit(1); - if (!m_writing) - do_write(); + if (!m_writing) + do_write(); } diff --git a/src/kernel/serial.h b/src/kernel/serial.h index ff31776..03c80ed 100644 --- a/src/kernel/serial.h +++ b/src/kernel/serial.h @@ -8,26 +8,26 @@ class serial_port { public: - /// Constructor. - /// \arg port The IO address of the serial port - serial_port(uint16_t port); + /// Constructor. + /// \arg port The IO address of the serial port + serial_port(uint16_t port); - serial_port(); + serial_port(); - void write(char c); - char read(); + void write(char c); + char read(); - void handle_interrupt(); + void handle_interrupt(); private: - bool m_writing; - uint16_t m_port; - kutil::bip_buffer m_out_buffer; - kutil::bip_buffer m_in_buffer; + bool m_writing; + uint16_t m_port; + kutil::bip_buffer m_out_buffer; + kutil::bip_buffer m_in_buffer; - void do_read(); - void do_write(); - void handle_error(uint16_t reg, uint8_t value); + void do_read(); + void do_write(); + void handle_error(uint16_t reg, uint8_t value); }; extern serial_port &g_com1; diff --git a/src/kernel/syscall.cpp b/src/kernel/syscall.cpp index 6ccc4b9..ce89e4f 100644 --- a/src/kernel/syscall.cpp +++ b/src/kernel/syscall.cpp @@ -8,7 +8,7 @@ #include "syscall.h" extern "C" { - void syscall_invalid(uint64_t call); + void syscall_invalid(uint64_t call); } uintptr_t syscall_registry[256] __attribute__((section(".syscall_registry"))); @@ -18,34 +18,34 @@ static constexpr size_t num_syscalls = sizeof(syscall_registry) / sizeof(syscall void syscall_invalid(uint64_t call) { - console *cons = console::get(); - cons->set_color(9); - cons->printf("\nReceived unknown syscall: %02x\n", call); + console *cons = console::get(); + cons->set_color(9); + cons->printf("\nReceived unknown syscall: %02x\n", call); - cons->printf(" Known syscalls:\n"); - cons->printf(" invalid %016lx\n", syscall_invalid); + cons->printf(" Known syscalls:\n"); + cons->printf(" invalid %016lx\n", syscall_invalid); - for (unsigned i = 0; i < num_syscalls; ++i) { - const char *name = syscall_names[i]; - uintptr_t handler = syscall_registry[i]; - if (name) - cons->printf(" %02x %10s %016lx\n", i, name, handler); - } + for (unsigned i = 0; i < num_syscalls; ++i) { + const char *name = syscall_names[i]; + uintptr_t handler = syscall_registry[i]; + if (name) + cons->printf(" %02x %10s %016lx\n", i, name, handler); + } - cons->set_color(); - _halt(); + cons->set_color(); + _halt(); } void syscall_initialize() { - kutil::memset(&syscall_registry, 0, sizeof(syscall_registry)); - kutil::memset(&syscall_names, 0, sizeof(syscall_names)); + kutil::memset(&syscall_registry, 0, sizeof(syscall_registry)); + kutil::memset(&syscall_names, 0, sizeof(syscall_names)); #define SYSCALL(id, name, result, ...) \ - syscall_registry[id] = reinterpret_cast(syscalls::name); \ - syscall_names[id] = #name; \ - log::debug(logs::syscall, "Enabling syscall 0x%02x as " #name , id); + syscall_registry[id] = reinterpret_cast(syscalls::name); \ + syscall_names[id] = #name; \ + log::debug(logs::syscall, "Enabling syscall 0x%02x as " #name , id); #include "j6/tables/syscalls.inc" #undef SYSCALL } diff --git a/src/kernel/syscalls/channel.cpp b/src/kernel/syscalls/channel.cpp index 9a5aedf..c98b7bf 100644 --- a/src/kernel/syscalls/channel.cpp +++ b/src/kernel/syscalls/channel.cpp @@ -9,24 +9,24 @@ namespace syscalls { j6_status_t channel_create(j6_handle_t *handle) { - construct_handle(handle); - return j6_status_ok; + construct_handle(handle); + return j6_status_ok; } j6_status_t channel_send(j6_handle_t handle, size_t *len, void *data) { - channel *c = get_handle(handle); - if (!c) return j6_err_invalid_arg; - return c->enqueue(len, data); + channel *c = get_handle(handle); + if (!c) return j6_err_invalid_arg; + return c->enqueue(len, data); } j6_status_t channel_receive(j6_handle_t handle, size_t *len, void *data) { - channel *c = get_handle(handle); - if (!c) return j6_err_invalid_arg; - return c->dequeue(len, data); + channel *c = get_handle(handle); + if (!c) return j6_err_invalid_arg; + return c->dequeue(len, data); } } // namespace syscalls diff --git a/src/kernel/syscalls/endpoint.cpp b/src/kernel/syscalls/endpoint.cpp index 410563a..d0c95ee 100644 --- a/src/kernel/syscalls/endpoint.cpp +++ b/src/kernel/syscalls/endpoint.cpp @@ -10,58 +10,58 @@ namespace syscalls { j6_status_t endpoint_create(j6_handle_t *handle) { - construct_handle(handle); - return j6_status_ok; + construct_handle(handle); + return j6_status_ok; } j6_status_t endpoint_send(j6_handle_t handle, j6_tag_t tag, size_t len, void *data) { - if (tag & j6_tag_system_flag) - return j6_err_invalid_arg; + if (tag & j6_tag_system_flag) + return j6_err_invalid_arg; - endpoint *e = get_handle(handle); - if (!e) return j6_err_invalid_arg; + endpoint *e = get_handle(handle); + if (!e) return j6_err_invalid_arg; - return e->send(tag, len, data); + return e->send(tag, len, data); } j6_status_t endpoint_receive(j6_handle_t handle, j6_tag_t *tag, size_t *len, void *data) { - if (!tag || !len || (*len && !data)) - return j6_err_invalid_arg; + if (!tag || !len || (*len && !data)) + return j6_err_invalid_arg; - endpoint *e = get_handle(handle); - if (!e) return j6_err_invalid_arg; + endpoint *e = get_handle(handle); + if (!e) return j6_err_invalid_arg; - j6_tag_t out_tag = j6_tag_invalid; - size_t out_len = *len; - j6_status_t s = e->receive(&out_tag, &out_len, data); - *tag = out_tag; - *len = out_len; - return s; + j6_tag_t out_tag = j6_tag_invalid; + size_t out_len = *len; + j6_status_t s = e->receive(&out_tag, &out_len, data); + *tag = out_tag; + *len = out_len; + return s; } j6_status_t endpoint_sendrecv(j6_handle_t handle, j6_tag_t *tag, size_t *len, void *data) { - if (!tag || (*tag & j6_tag_system_flag)) - return j6_err_invalid_arg; + if (!tag || (*tag & j6_tag_system_flag)) + return j6_err_invalid_arg; - endpoint *e = get_handle(handle); - if (!e) return j6_err_invalid_arg; + endpoint *e = get_handle(handle); + if (!e) return j6_err_invalid_arg; - j6_status_t status = e->send(*tag, *len, data); - if (status != j6_status_ok) - return status; + j6_status_t status = e->send(*tag, *len, data); + if (status != j6_status_ok) + return status; - j6_tag_t out_tag = j6_tag_invalid; - size_t out_len = *len; - j6_status_t s = e->receive(&out_tag, &out_len, data); - *tag = out_tag; - *len = out_len; - return s; + j6_tag_t out_tag = j6_tag_invalid; + size_t out_len = *len; + j6_status_t s = e->receive(&out_tag, &out_len, data); + *tag = out_tag; + *len = out_len; + return s; } } // namespace syscalls diff --git a/src/kernel/syscalls/helpers.h b/src/kernel/syscalls/helpers.h index ff5caa3..d96936a 100644 --- a/src/kernel/syscalls/helpers.h +++ b/src/kernel/syscalls/helpers.h @@ -11,38 +11,38 @@ namespace syscalls { template T * construct_handle(j6_handle_t *handle, Args... args) { - process &p = process::current(); - T *o = new T {args...}; - *handle = p.add_handle(o); - return o; + process &p = process::current(); + T *o = new T {args...}; + *handle = p.add_handle(o); + return o; } template T * get_handle(j6_handle_t handle) { - process &p = process::current(); - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != T::type) - return nullptr; - return static_cast(o); + process &p = process::current(); + kobject *o = p.lookup_handle(handle); + if (!o || o->get_type() != T::type) + return nullptr; + return static_cast(o); } template <> inline kobject * get_handle(j6_handle_t handle) { - process &p = process::current(); - return p.lookup_handle(handle); + process &p = process::current(); + return p.lookup_handle(handle); } template T * remove_handle(j6_handle_t handle) { - T *o = get_handle(handle); - if (o) { - process &p = process::current(); - p.remove_handle(handle); - } - return o; + T *o = get_handle(handle); + if (o) { + process &p = process::current(); + p.remove_handle(handle); + } + return o; } } diff --git a/src/kernel/syscalls/object.cpp b/src/kernel/syscalls/object.cpp index 895c953..1882740 100644 --- a/src/kernel/syscalls/object.cpp +++ b/src/kernel/syscalls/object.cpp @@ -11,39 +11,39 @@ namespace syscalls { j6_status_t object_koid(j6_handle_t handle, j6_koid_t *koid) { - if (koid == nullptr) - return j6_err_invalid_arg; + if (koid == nullptr) + return j6_err_invalid_arg; - kobject *obj = get_handle(handle); - if (!obj) - return j6_err_invalid_arg; + kobject *obj = get_handle(handle); + if (!obj) + return j6_err_invalid_arg; - *koid = obj->koid(); - return j6_status_ok; + *koid = obj->koid(); + return j6_status_ok; } j6_status_t object_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs) { - kobject *obj = get_handle(handle); - if (!obj) - return j6_err_invalid_arg; + kobject *obj = get_handle(handle); + if (!obj) + return j6_err_invalid_arg; - j6_signal_t current = obj->signals(); - if ((current & mask) != 0) { - *sigs = current; - return j6_status_ok; - } + j6_signal_t current = obj->signals(); + if ((current & mask) != 0) { + *sigs = current; + return j6_status_ok; + } - thread &th = thread::current(); - obj->add_blocked_thread(&th); - th.wait_on_signals(mask); + thread &th = thread::current(); + obj->add_blocked_thread(&th); + th.wait_on_signals(mask); - j6_status_t result = th.get_wait_result(); - if (result == j6_status_ok) { - *sigs = th.get_wait_data(); - } - return result; + j6_status_t result = th.get_wait_result(); + if (result == j6_status_ok) { + *sigs = th.get_wait_data(); + } + return result; } j6_status_t @@ -70,14 +70,14 @@ object_wait_many(j6_handle_t *handles, uint32_t count, j6_signal_t mask, j6_hand objects.append(obj); } - thread &th = thread::current(); + thread &th = thread::current(); for (auto *obj : objects) obj->add_blocked_thread(&th); - th.wait_on_signals(mask); + th.wait_on_signals(mask); - j6_status_t result = th.get_wait_result(); - if (result != j6_status_ok) + j6_status_t result = th.get_wait_result(); + if (result != j6_status_ok) return result; *handle = j6_handle_invalid; @@ -98,26 +98,26 @@ object_wait_many(j6_handle_t *handles, uint32_t count, j6_signal_t mask, j6_hand j6_status_t object_signal(j6_handle_t handle, j6_signal_t signals) { - if ((signals & j6_signal_user_mask) != signals) - return j6_err_invalid_arg; + if ((signals & j6_signal_user_mask) != signals) + return j6_err_invalid_arg; - kobject *obj = get_handle(handle); - if (!obj) - return j6_err_invalid_arg; + kobject *obj = get_handle(handle); + if (!obj) + return j6_err_invalid_arg; - obj->assert_signal(signals); - return j6_status_ok; + obj->assert_signal(signals); + return j6_status_ok; } j6_status_t object_close(j6_handle_t handle) { - kobject *obj = get_handle(handle); - if (!obj) - return j6_err_invalid_arg; + kobject *obj = get_handle(handle); + if (!obj) + return j6_err_invalid_arg; - obj->close(); - return j6_status_ok; + obj->close(); + return j6_status_ok; } } // namespace syscalls diff --git a/src/kernel/syscalls/process.cpp b/src/kernel/syscalls/process.cpp index 7912dc9..914d66d 100644 --- a/src/kernel/syscalls/process.cpp +++ b/src/kernel/syscalls/process.cpp @@ -10,50 +10,50 @@ namespace syscalls { j6_status_t process_create(j6_handle_t *handle) { - process *child = construct_handle(handle); - log::debug(logs::task, "Process %llx created", child->koid()); - return j6_status_ok; + process *child = construct_handle(handle); + log::debug(logs::task, "Process %llx created", child->koid()); + return j6_status_ok; } j6_status_t process_start(j6_handle_t handle, uintptr_t entrypoint, j6_handle_t *handles, size_t handle_count) { - process &p = process::current(); - process *c = get_handle(handle); - if (handle_count && !handles) - return j6_err_invalid_arg; + process &p = process::current(); + process *c = get_handle(handle); + if (handle_count && !handles) + return j6_err_invalid_arg; - for (size_t i = 0; i < handle_count; ++i) { - kobject *o = p.lookup_handle(handles[i]); - if (o) c->add_handle(o); - } + for (size_t i = 0; i < handle_count; ++i) { + kobject *o = p.lookup_handle(handles[i]); + if (o) c->add_handle(o); + } - return j6_err_nyi; + return j6_err_nyi; } j6_status_t process_kill(j6_handle_t handle) { - process &p = process::current(); - process *c = get_handle(handle); - if (!c) return j6_err_invalid_arg; + process &p = process::current(); + process *c = get_handle(handle); + if (!c) return j6_err_invalid_arg; - log::debug(logs::task, "Process %llx killed by process %llx", c->koid(), p.koid()); - c->exit(-1u); + log::debug(logs::task, "Process %llx killed by process %llx", c->koid(), p.koid()); + c->exit(-1u); - return j6_status_ok; + return j6_status_ok; } j6_status_t process_exit(int32_t status) { - process &p = process::current(); - log::debug(logs::task, "Process %llx exiting with code %d", p.koid(), status); + process &p = process::current(); + log::debug(logs::task, "Process %llx exiting with code %d", p.koid(), status); - p.exit(status); + p.exit(status); - log::error(logs::task, "returned to exit syscall"); - return j6_err_unexpected; + log::error(logs::task, "returned to exit syscall"); + return j6_err_unexpected; } } // namespace syscalls diff --git a/src/kernel/syscalls/system.cpp b/src/kernel/syscalls/system.cpp index a889125..3be6f5a 100644 --- a/src/kernel/syscalls/system.cpp +++ b/src/kernel/syscalls/system.cpp @@ -17,64 +17,64 @@ namespace syscalls { j6_status_t system_log(const char *message) { - if (message == nullptr) - return j6_err_invalid_arg; + if (message == nullptr) + return j6_err_invalid_arg; - thread &th = thread::current(); - log::info(logs::syscall, "Message[%llx]: %s", th.koid(), message); - return j6_status_ok; + thread &th = thread::current(); + log::info(logs::syscall, "Message[%llx]: %s", th.koid(), message); + return j6_status_ok; } j6_status_t system_noop() { - thread &th = thread::current(); - log::debug(logs::syscall, "Thread %llx called noop syscall.", th.koid()); - return j6_status_ok; + thread &th = thread::current(); + log::debug(logs::syscall, "Thread %llx called noop syscall.", th.koid()); + return j6_status_ok; } j6_status_t system_get_log(j6_handle_t sys, void *buffer, size_t *size) { - if (!size || (*size && !buffer)) - return j6_err_invalid_arg; + if (!size || (*size && !buffer)) + return j6_err_invalid_arg; - size_t orig_size = *size; - *size = g_logger.get_entry(buffer, *size); - if (!g_logger.has_log()) - system::get().deassert_signal(j6_signal_system_has_log); + size_t orig_size = *size; + *size = g_logger.get_entry(buffer, *size); + if (!g_logger.has_log()) + system::get().deassert_signal(j6_signal_system_has_log); - return (*size > orig_size) ? j6_err_insufficient : j6_status_ok; + return (*size > orig_size) ? j6_err_insufficient : j6_status_ok; } j6_status_t system_bind_irq(j6_handle_t sys, j6_handle_t endp, unsigned irq) { - // TODO: check capabilities on sys handle - endpoint *e = get_handle(endp); - if (!e) return j6_err_invalid_arg; + // TODO: check capabilities on sys handle + endpoint *e = get_handle(endp); + if (!e) return j6_err_invalid_arg; - if (device_manager::get().bind_irq(irq, e)) - return j6_status_ok; + if (device_manager::get().bind_irq(irq, e)) + return j6_status_ok; - return j6_err_invalid_arg; + return j6_err_invalid_arg; } j6_status_t system_map_phys(j6_handle_t sys, j6_handle_t *vma_handle, uintptr_t phys_addr, size_t size, uint32_t flags) { - // TODO: check capabilities on sys handle - if (!vma_handle) return j6_err_invalid_arg; + // TODO: check capabilities on sys handle + if (!vma_handle) return j6_err_invalid_arg; - // TODO: check to see if frames are already used? How would that collide with - // the bootloader's allocated pages already being marked used? - if (!(flags & vm_flags::mmio)) - frame_allocator::get().used(phys_addr, memory::page_count(size)); + // TODO: check to see if frames are already used? How would that collide with + // the bootloader's allocated pages already being marked used? + if (!(flags & vm_flags::mmio)) + frame_allocator::get().used(phys_addr, memory::page_count(size)); - vm_flags vmf = (static_cast(flags) & vm_flags::driver_mask); - construct_handle(vma_handle, phys_addr, size, vmf); + vm_flags vmf = (static_cast(flags) & vm_flags::driver_mask); + construct_handle(vma_handle, phys_addr, size, vmf); - return j6_status_ok; + return j6_status_ok; } } // namespace syscalls diff --git a/src/kernel/syscalls/thread.cpp b/src/kernel/syscalls/thread.cpp index 3dd460a..f35f67c 100644 --- a/src/kernel/syscalls/thread.cpp +++ b/src/kernel/syscalls/thread.cpp @@ -10,48 +10,48 @@ namespace syscalls { j6_status_t thread_create(void *rip, j6_handle_t *handle) { - thread &parent = thread::current(); - process &p = parent.parent(); + thread &parent = thread::current(); + process &p = parent.parent(); - thread *child = p.create_thread(); - child->add_thunk_user(reinterpret_cast(rip)); - *handle = child->self_handle(); - child->clear_state(thread::state::loading); - child->set_state(thread::state::ready); + thread *child = p.create_thread(); + child->add_thunk_user(reinterpret_cast(rip)); + *handle = child->self_handle(); + child->clear_state(thread::state::loading); + child->set_state(thread::state::ready); - log::debug(logs::task, "Thread %llx spawned new thread %llx, handle %d", - parent.koid(), child->koid(), *handle); + log::debug(logs::task, "Thread %llx spawned new thread %llx, handle %d", + parent.koid(), child->koid(), *handle); - return j6_status_ok; + return j6_status_ok; } j6_status_t thread_exit(int32_t status) { - thread &th = thread::current(); - log::debug(logs::task, "Thread %llx exiting with code %d", th.koid(), status); - th.exit(status); + thread &th = thread::current(); + log::debug(logs::task, "Thread %llx exiting with code %d", th.koid(), status); + th.exit(status); - log::error(logs::task, "returned to exit syscall"); - return j6_err_unexpected; + log::error(logs::task, "returned to exit syscall"); + return j6_err_unexpected; } j6_status_t thread_pause() { - thread &th = thread::current(); - th.wait_on_signals(-1ull); - return j6_status_ok; + thread &th = thread::current(); + th.wait_on_signals(-1ull); + return j6_status_ok; } j6_status_t thread_sleep(uint64_t til) { - thread &th = thread::current(); - log::debug(logs::task, "Thread %llx sleeping until %llu", th.koid(), til); + thread &th = thread::current(); + log::debug(logs::task, "Thread %llx sleeping until %llu", th.koid(), til); - th.wait_on_time(til); - return j6_status_ok; + th.wait_on_time(til); + return j6_status_ok; } } // namespace syscalls diff --git a/src/kernel/syscalls/vm_area.cpp b/src/kernel/syscalls/vm_area.cpp index 95984da..e75ee42 100644 --- a/src/kernel/syscalls/vm_area.cpp +++ b/src/kernel/syscalls/vm_area.cpp @@ -13,57 +13,57 @@ namespace syscalls { j6_status_t vma_create(j6_handle_t *handle, size_t size, uint32_t flags) { - vm_flags f = vm_flags::user_mask & flags; - construct_handle(handle, size, f); - return j6_status_ok; + vm_flags f = vm_flags::user_mask & flags; + construct_handle(handle, size, f); + return j6_status_ok; } j6_status_t vma_create_map(j6_handle_t *handle, size_t size, uintptr_t base, uint32_t flags) { - vm_flags f = vm_flags::user_mask & flags; - vm_area *a = construct_handle(handle, size, f); - process::current().space().add(base, a); - return j6_status_ok; + vm_flags f = vm_flags::user_mask & flags; + vm_area *a = construct_handle(handle, size, f); + process::current().space().add(base, a); + return j6_status_ok; } j6_status_t vma_map(j6_handle_t handle, j6_handle_t proc, uintptr_t base) { - vm_area *a = get_handle(handle); - if (!a) return j6_err_invalid_arg; + vm_area *a = get_handle(handle); + if (!a) return j6_err_invalid_arg; - process *p = get_handle(proc); - if (!p) return j6_err_invalid_arg; + process *p = get_handle(proc); + if (!p) return j6_err_invalid_arg; - p->space().add(base, a); - return j6_status_ok; + p->space().add(base, a); + return j6_status_ok; } j6_status_t vma_unmap(j6_handle_t handle, j6_handle_t proc) { - vm_area *a = get_handle(handle); - if (!a) return j6_err_invalid_arg; + vm_area *a = get_handle(handle); + if (!a) return j6_err_invalid_arg; - process *p = get_handle(proc); - if (!p) return j6_err_invalid_arg; + process *p = get_handle(proc); + if (!p) return j6_err_invalid_arg; - p->space().remove(a); - return j6_status_ok; + p->space().remove(a); + return j6_status_ok; } j6_status_t vma_resize(j6_handle_t handle, size_t *size) { - if (!size) - return j6_err_invalid_arg; + if (!size) + return j6_err_invalid_arg; - vm_area *a = get_handle(handle); - if (!a) return j6_err_invalid_arg; + vm_area *a = get_handle(handle); + if (!a) return j6_err_invalid_arg; - *size = a->resize(*size); - return j6_status_ok; + *size = a->resize(*size); + return j6_status_ok; } diff --git a/src/kernel/tss.cpp b/src/kernel/tss.cpp index 780cac5..a894c30 100644 --- a/src/kernel/tss.cpp +++ b/src/kernel/tss.cpp @@ -17,52 +17,52 @@ TSS &g_bsp_tss = __g_bsp_tss_storage.value; TSS::TSS() { - kutil::memset(this, 0, sizeof(TSS)); - m_iomap_offset = sizeof(TSS); + kutil::memset(this, 0, sizeof(TSS)); + m_iomap_offset = sizeof(TSS); } TSS & TSS::current() { - return *current_cpu().tss; + return *current_cpu().tss; } uintptr_t & TSS::ring_stack(unsigned ring) { - kassert(ring < 3, "Bad ring passed to TSS::ring_stack."); - return m_rsp[ring]; + kassert(ring < 3, "Bad ring passed to TSS::ring_stack."); + return m_rsp[ring]; } uintptr_t & TSS::ist_stack(unsigned ist) { - kassert(ist > 0 && ist < 7, "Bad ist passed to TSS::ist_stack."); - return m_ist[ist]; + kassert(ist > 0 && ist < 7, "Bad ist passed to TSS::ist_stack."); + return m_ist[ist]; } void TSS::create_ist_stacks(uint8_t ist_entries) { - extern vm_area_guarded &g_kernel_stacks; - using memory::frame_size; - using memory::kernel_stack_pages; - constexpr size_t stack_bytes = kernel_stack_pages * frame_size; + extern vm_area_guarded &g_kernel_stacks; + using memory::frame_size; + using memory::kernel_stack_pages; + constexpr size_t stack_bytes = kernel_stack_pages * frame_size; - for (unsigned ist = 1; ist < 8; ++ist) { - if (!(ist_entries & (1 << ist))) continue; + for (unsigned ist = 1; ist < 8; ++ist) { + if (!(ist_entries & (1 << ist))) continue; - // Two zero entries at the top for the null frame - uintptr_t stack_bottom = g_kernel_stacks.get_section(); - uintptr_t stack_top = stack_bottom + stack_bytes - 2 * sizeof(uintptr_t); + // Two zero entries at the top for the null frame + uintptr_t stack_bottom = g_kernel_stacks.get_section(); + uintptr_t stack_top = stack_bottom + stack_bytes - 2 * sizeof(uintptr_t); - log::debug(logs::memory, "Created IST stack at %016lx size 0x%lx", - stack_bottom, stack_bytes); + log::debug(logs::memory, "Created IST stack at %016lx size 0x%lx", + stack_bottom, stack_bytes); - // Pre-realize these stacks, they're no good if they page fault - for (unsigned i = 0; i < kernel_stack_pages; ++i) - *reinterpret_cast(stack_bottom + i * frame_size) = 0; + // Pre-realize these stacks, they're no good if they page fault + for (unsigned i = 0; i < kernel_stack_pages; ++i) + *reinterpret_cast(stack_bottom + i * frame_size) = 0; - ist_stack(ist) = stack_top; - } + ist_stack(ist) = stack_top; + } } diff --git a/src/kernel/tss.h b/src/kernel/tss.h index 4bf8d1a..83da6cc 100644 --- a/src/kernel/tss.h +++ b/src/kernel/tss.h @@ -7,33 +7,33 @@ class TSS { public: - TSS(); + TSS(); - /// Get the currently running CPU's TSS. - static TSS & current(); + /// Get the currently running CPU's TSS. + static TSS & current(); - /// Ring stack accessor. Returns a mutable reference. - /// \arg ring Which ring (0-3) to get the stack for - /// \returns A mutable reference to the stack pointer - uintptr_t & ring_stack(unsigned ring); + /// Ring stack accessor. Returns a mutable reference. + /// \arg ring Which ring (0-3) to get the stack for + /// \returns A mutable reference to the stack pointer + uintptr_t & ring_stack(unsigned ring); - /// IST stack accessor. Returns a mutable reference. - /// \arg ist Which IST entry (1-7) to get the stack for - /// \returns A mutable reference to the stack pointer - uintptr_t & ist_stack(unsigned ist); + /// IST stack accessor. Returns a mutable reference. + /// \arg ist Which IST entry (1-7) to get the stack for + /// \returns A mutable reference to the stack pointer + uintptr_t & ist_stack(unsigned ist); - /// Allocate new stacks for the given IST entries. - /// \arg ist_entries A bitmap of used IST entries - void create_ist_stacks(uint8_t ist_entries); + /// Allocate new stacks for the given IST entries. + /// \arg ist_entries A bitmap of used IST entries + void create_ist_stacks(uint8_t ist_entries); private: - uint32_t m_reserved0; + uint32_t m_reserved0; - uintptr_t m_rsp[3]; // stack pointers for CPL 0-2 - uintptr_t m_ist[8]; // ist[0] is reserved + uintptr_t m_rsp[3]; // stack pointers for CPL 0-2 + uintptr_t m_ist[8]; // ist[0] is reserved - uint64_t m_reserved1; - uint16_t m_reserved2; - uint16_t m_iomap_offset; + uint64_t m_reserved1; + uint16_t m_reserved2; + uint16_t m_iomap_offset; } __attribute__ ((packed)); diff --git a/src/kernel/vm_space.cpp b/src/kernel/vm_space.cpp index 6c045db..7e9a070 100644 --- a/src/kernel/vm_space.cpp +++ b/src/kernel/vm_space.cpp @@ -13,293 +13,293 @@ static uint64_t kernel_areas[num_kernel_areas * 2]; int vm_space::area::compare(const vm_space::area &o) const { - if (base > o.base) return 1; - else if (base < o.base) return -1; - else return 0; + if (base > o.base) return 1; + else if (base < o.base) return -1; + else return 0; } bool vm_space::area::operator==(const vm_space::area &o) const { - return o.base == base && o.area == area; + return o.base == base && o.area == area; } // Kernel address space contsructor vm_space::vm_space(page_table *p) : - m_kernel {true}, - m_pml4 {p}, - m_areas {reinterpret_cast(kernel_areas), 0, num_kernel_areas} + m_kernel {true}, + m_pml4 {p}, + m_areas {reinterpret_cast(kernel_areas), 0, num_kernel_areas} {} vm_space::vm_space() : - m_kernel {false} + m_kernel {false} { - m_pml4 = page_table::get_table_page(); - page_table *kpml4 = kernel_space().m_pml4; + m_pml4 = page_table::get_table_page(); + page_table *kpml4 = kernel_space().m_pml4; - kutil::memset(m_pml4, 0, memory::frame_size/2); - for (unsigned i = memory::pml4e_kernel; i < memory::table_entries; ++i) - m_pml4->entries[i] = kpml4->entries[i]; + kutil::memset(m_pml4, 0, memory::frame_size/2); + for (unsigned i = memory::pml4e_kernel; i < memory::table_entries; ++i) + m_pml4->entries[i] = kpml4->entries[i]; } vm_space::~vm_space() { - for (auto &a : m_areas) { - bool free = a.area->remove_from(this); - clear(*a.area, 0, memory::page_count(a.area->size()), free); - a.area->handle_release(); - } + for (auto &a : m_areas) { + bool free = a.area->remove_from(this); + clear(*a.area, 0, memory::page_count(a.area->size()), free); + a.area->handle_release(); + } - kassert(!is_kernel(), "Kernel vm_space destructor!"); - if (active()) - kernel_space().activate(); + kassert(!is_kernel(), "Kernel vm_space destructor!"); + if (active()) + kernel_space().activate(); - // All VMAs have been removed by now, so just - // free all remaining pages and tables - m_pml4->free(page_table::level::pml4); + // All VMAs have been removed by now, so just + // free all remaining pages and tables + m_pml4->free(page_table::level::pml4); } vm_space & vm_space::kernel_space() { - return process::kernel_process().space(); + return process::kernel_process().space(); } bool vm_space::add(uintptr_t base, vm_area *area) { - //TODO: check for collisions - m_areas.sorted_insert({base, area}); - area->add_to(this); - area->handle_retain(); - return true; + //TODO: check for collisions + m_areas.sorted_insert({base, area}); + area->add_to(this); + area->handle_retain(); + return true; } bool vm_space::remove(vm_area *area) { - for (auto &a : m_areas) { - if (a.area == area) { - bool free = area->remove_from(this); - clear(*area, 0, memory::page_count(area->size()), free); - m_areas.remove(a); - area->handle_release(); - return true; - } - } - return false; + for (auto &a : m_areas) { + if (a.area == area) { + bool free = area->remove_from(this); + clear(*area, 0, memory::page_count(area->size()), free); + m_areas.remove(a); + area->handle_release(); + return true; + } + } + return false; } bool vm_space::can_resize(const vm_area &vma, size_t size) const { - uintptr_t base = 0; - unsigned n = m_areas.count(); - for (unsigned i = 0; i < n - 1; ++i) { - const area &prev = m_areas[i - 1]; - if (prev.area != &vma) - continue; + uintptr_t base = 0; + unsigned n = m_areas.count(); + for (unsigned i = 0; i < n - 1; ++i) { + const area &prev = m_areas[i - 1]; + if (prev.area != &vma) + continue; - base = prev.base; - const area &next = m_areas[i]; - if (prev.base + size > next.base) - return false; - } + base = prev.base; + const area &next = m_areas[i]; + if (prev.base + size > next.base) + return false; + } - uintptr_t end = base + size; - uintptr_t space_end = is_kernel() ? - uint64_t(-1) : 0x7fffffffffff; + uintptr_t end = base + size; + uintptr_t space_end = is_kernel() ? + uint64_t(-1) : 0x7fffffffffff; - return end <= space_end; + return end <= space_end; } vm_area * vm_space::get(uintptr_t addr, uintptr_t *base) { - for (auto &a : m_areas) { - uintptr_t end = a.base + a.area->size(); - if (addr >= a.base && addr < end) { - if (base) *base = a.base; - return a.area; - } - } - return nullptr; + for (auto &a : m_areas) { + uintptr_t end = a.base + a.area->size(); + if (addr >= a.base && addr < end) { + if (base) *base = a.base; + return a.area; + } + } + return nullptr; } bool vm_space::find_vma(const vm_area &vma, uintptr_t &base) const { - for (auto &a : m_areas) { - if (a.area != &vma) continue; - base = a.base; - return true; - } - return false; + for (auto &a : m_areas) { + if (a.area != &vma) continue; + base = a.base; + return true; + } + return false; } void vm_space::copy_from(const vm_space &source, const vm_area &vma) { - uintptr_t to = 0; - uintptr_t from = 0; - if (!find_vma(vma, from) || !source.find_vma(vma, from)) - return; + uintptr_t to = 0; + uintptr_t from = 0; + if (!find_vma(vma, from) || !source.find_vma(vma, from)) + return; - size_t count = memory::page_count(vma.size()); - page_table::iterator dit {to, m_pml4}; - page_table::iterator sit {from, source.m_pml4}; + size_t count = memory::page_count(vma.size()); + page_table::iterator dit {to, m_pml4}; + page_table::iterator sit {from, source.m_pml4}; - while (count--) { - uint64_t &e = dit.entry(page_table::level::pt); - if (e & page_table::flag::present) { - // TODO: handle clobbering mapping - } - e = sit.entry(page_table::level::pt); - } + while (count--) { + uint64_t &e = dit.entry(page_table::level::pt); + if (e & page_table::flag::present) { + // TODO: handle clobbering mapping + } + e = sit.entry(page_table::level::pt); + } } void vm_space::page_in(const vm_area &vma, uintptr_t offset, uintptr_t phys, size_t count) { - using memory::frame_size; - kutil::scoped_lock lock {m_lock}; + using memory::frame_size; + kutil::scoped_lock lock {m_lock}; - uintptr_t base = 0; - if (!find_vma(vma, base)) - return; + uintptr_t base = 0; + if (!find_vma(vma, base)) + return; - uintptr_t virt = base + offset; - page_table::flag flags = - page_table::flag::present | - (m_kernel ? page_table::flag::none : page_table::flag::user) | - ((vma.flags() && vm_flags::write) ? page_table::flag::write : page_table::flag::none) | - ((vma.flags() && vm_flags::write_combine) ? page_table::flag::wc : page_table::flag::none); + uintptr_t virt = base + offset; + page_table::flag flags = + page_table::flag::present | + (m_kernel ? page_table::flag::none : page_table::flag::user) | + ((vma.flags() && vm_flags::write) ? page_table::flag::write : page_table::flag::none) | + ((vma.flags() && vm_flags::write_combine) ? page_table::flag::wc : page_table::flag::none); - page_table::iterator it {virt, m_pml4}; + page_table::iterator it {virt, m_pml4}; - for (size_t i = 0; i < count; ++i) { - uint64_t &entry = it.entry(page_table::level::pt); - entry = (phys + i * frame_size) | flags; - log::debug(logs::paging, "Setting entry for %016llx: %016llx [%04llx]", - it.vaddress(), (phys + i * frame_size), flags); - ++it; - } + for (size_t i = 0; i < count; ++i) { + uint64_t &entry = it.entry(page_table::level::pt); + entry = (phys + i * frame_size) | flags; + log::debug(logs::paging, "Setting entry for %016llx: %016llx [%04llx]", + it.vaddress(), (phys + i * frame_size), flags); + ++it; + } } void vm_space::clear(const vm_area &vma, uintptr_t offset, size_t count, bool free) { - using memory::frame_size; - kutil::scoped_lock lock {m_lock}; + using memory::frame_size; + kutil::scoped_lock lock {m_lock}; - uintptr_t base = 0; - if (!find_vma(vma, base)) - return; + uintptr_t base = 0; + if (!find_vma(vma, base)) + return; - uintptr_t addr = base + offset; - uintptr_t free_start = 0; - size_t free_count = 0; + uintptr_t addr = base + offset; + uintptr_t free_start = 0; + size_t free_count = 0; - frame_allocator &fa = frame_allocator::get(); - page_table::iterator it {addr, m_pml4}; + frame_allocator &fa = frame_allocator::get(); + page_table::iterator it {addr, m_pml4}; - while (count--) { - uint64_t &e = it.entry(page_table::level::pt); - uintptr_t phys = e & ~0xfffull; + while (count--) { + uint64_t &e = it.entry(page_table::level::pt); + uintptr_t phys = e & ~0xfffull; - if (e & page_table::flag::present) { - if (free_count && phys == free_start + (free_count * frame_size)) { - ++free_count; - } else { - if (free && free_count) - fa.free(free_start, free_count); - free_start = phys; - free_count = 1; - } - } + if (e & page_table::flag::present) { + if (free_count && phys == free_start + (free_count * frame_size)) { + ++free_count; + } else { + if (free && free_count) + fa.free(free_start, free_count); + free_start = phys; + free_count = 1; + } + } - e = 0; - ++it; - } + e = 0; + ++it; + } - if (free && free_count) - fa.free(free_start, free_count); + if (free && free_count) + fa.free(free_start, free_count); } uintptr_t vm_space::lookup(const vm_area &vma, uintptr_t offset) { - uintptr_t base = 0; - if (!find_vma(vma, base)) - return 0; - return base + offset; + uintptr_t base = 0; + if (!find_vma(vma, base)) + return 0; + return base + offset; } bool vm_space::active() const { - uintptr_t pml4 = 0; - __asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (pml4) ); - return memory::to_virtual(pml4 & ~0xfffull) == m_pml4; + uintptr_t pml4 = 0; + __asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (pml4) ); + return memory::to_virtual(pml4 & ~0xfffull) == m_pml4; } void vm_space::activate() const { - constexpr uint64_t phys_mask = ~memory::page_offset & ~0xfffull; - uintptr_t p = reinterpret_cast(m_pml4) & phys_mask; - __asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (p) ); + constexpr uint64_t phys_mask = ~memory::page_offset & ~0xfffull; + uintptr_t p = reinterpret_cast(m_pml4) & phys_mask; + __asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (p) ); } void vm_space::initialize_tcb(TCB &tcb) { - tcb.pml4 = - reinterpret_cast(m_pml4) & - ~memory::page_offset; + tcb.pml4 = + reinterpret_cast(m_pml4) & + ~memory::page_offset; } bool vm_space::handle_fault(uintptr_t addr, fault_type fault) { - // TODO: Handle more fult types - if (fault && fault_type::present) - return false; + // TODO: Handle more fult types + if (fault && fault_type::present) + return false; - uintptr_t base = 0; - vm_area *area = get(addr, &base); - if (!area) - return false; + uintptr_t base = 0; + vm_area *area = get(addr, &base); + if (!area) + return false; - uintptr_t offset = (addr & ~0xfffull) - base; - uintptr_t phys_page = 0; - if (!area->get_page(offset, phys_page)) - return false; + uintptr_t offset = (addr & ~0xfffull) - base; + uintptr_t phys_page = 0; + if (!area->get_page(offset, phys_page)) + return false; - void *mem = memory::to_virtual(phys_page); - if (area->flags() && vm_flags::zero) - kutil::memset(mem, 0, memory::frame_size); + void *mem = memory::to_virtual(phys_page); + if (area->flags() && vm_flags::zero) + kutil::memset(mem, 0, memory::frame_size); - page_in(*area, offset, phys_page, 1); - return true; + page_in(*area, offset, phys_page, 1); + return true; } size_t vm_space::copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length) { - uintptr_t ifrom = reinterpret_cast(from); - uintptr_t ito = reinterpret_cast(to); + uintptr_t ifrom = reinterpret_cast(from); + uintptr_t ito = reinterpret_cast(to); - page_table::iterator sit {ifrom, source.m_pml4}; - page_table::iterator dit {ito, dest.m_pml4}; + page_table::iterator sit {ifrom, source.m_pml4}; + page_table::iterator dit {ito, dest.m_pml4}; - // TODO: iterate page mappings and continue copying. For now i'm blindly - // assuming both buffers are fully contained within single pages - kutil::memcpy( - memory::to_virtual((*dit & ~0xfffull) | (ito & 0xffful)), - memory::to_virtual((*sit & ~0xfffull) | (ifrom & 0xffful)), - length); + // TODO: iterate page mappings and continue copying. For now i'm blindly + // assuming both buffers are fully contained within single pages + kutil::memcpy( + memory::to_virtual((*dit & ~0xfffull) | (ito & 0xffful)), + memory::to_virtual((*sit & ~0xfffull) | (ifrom & 0xffful)), + length); - return length; + return length; } diff --git a/src/kernel/vm_space.h b/src/kernel/vm_space.h index 8f66351..92c2aaf 100644 --- a/src/kernel/vm_space.h +++ b/src/kernel/vm_space.h @@ -16,120 +16,120 @@ class vm_area; class vm_space { public: - /// Constructor for the kernel address space - /// \arg pml4 The existing kernel PML4 - vm_space(page_table *pml4); + /// Constructor for the kernel address space + /// \arg pml4 The existing kernel PML4 + vm_space(page_table *pml4); - /// Constructor. Creates a new address space. - vm_space(); + /// Constructor. Creates a new address space. + vm_space(); - ~vm_space(); + ~vm_space(); - /// Add a virtual memorty area to this address space - /// \arg base The starting address of the area - /// \arg area The area to add - /// \returns True if the add succeeded - bool add(uintptr_t base, vm_area *area); + /// Add a virtual memorty area to this address space + /// \arg base The starting address of the area + /// \arg area The area to add + /// \returns True if the add succeeded + bool add(uintptr_t base, vm_area *area); - /// Remove a virtual memory area from this address space - /// \arg area The area to remove - /// \returns True if the area was removed - bool remove(vm_area *area); + /// Remove a virtual memory area from this address space + /// \arg area The area to remove + /// \returns True if the area was removed + bool remove(vm_area *area); - /// Get the virtual memory area corresponding to an address - /// \arg addr The address to check - /// \arg base [out] if not null, receives the base address of the area - /// \returns The vm_area, or nullptr if not found - vm_area * get(uintptr_t addr, uintptr_t *base = nullptr); + /// Get the virtual memory area corresponding to an address + /// \arg addr The address to check + /// \arg base [out] if not null, receives the base address of the area + /// \returns The vm_area, or nullptr if not found + vm_area * get(uintptr_t addr, uintptr_t *base = nullptr); - /// Check if this is the kernel space - inline bool is_kernel() const { return m_kernel; } + /// Check if this is the kernel space + inline bool is_kernel() const { return m_kernel; } - /// Get the kernel virtual memory space - static vm_space & kernel_space(); + /// Get the kernel virtual memory space + static vm_space & kernel_space(); - /// Map virtual addressses to the given physical pages - /// \arg area The VMA this mapping applies to - /// \arg offset Offset of the starting virutal address from the VMA base - /// \arg phys The starting physical address - /// \arg count The number of contiugous physical pages to map - void page_in(const vm_area &area, uintptr_t offset, uintptr_t phys, size_t count); + /// Map virtual addressses to the given physical pages + /// \arg area The VMA this mapping applies to + /// \arg offset Offset of the starting virutal address from the VMA base + /// \arg phys The starting physical address + /// \arg count The number of contiugous physical pages to map + void page_in(const vm_area &area, uintptr_t offset, uintptr_t phys, size_t count); - /// Clear mappings from the given region - /// \arg area The VMA these mappings applies to - /// \arg offset Offset of the starting virutal address from the VMA base - /// \arg count The number of pages worth of mappings to clear - /// \arg free If true, free the pages back to the system - void clear(const vm_area &vma, uintptr_t start, size_t count, bool free = false); + /// Clear mappings from the given region + /// \arg area The VMA these mappings applies to + /// \arg offset Offset of the starting virutal address from the VMA base + /// \arg count The number of pages worth of mappings to clear + /// \arg free If true, free the pages back to the system + void clear(const vm_area &vma, uintptr_t start, size_t count, bool free = false); - /// Look up the address of a given VMA's offset - uintptr_t lookup(const vm_area &vma, uintptr_t offset); + /// Look up the address of a given VMA's offset + uintptr_t lookup(const vm_area &vma, uintptr_t offset); - /// Check if this space is the current active space - bool active() const; + /// Check if this space is the current active space + bool active() const; - /// Set this space as the current active space - void activate() const; + /// Set this space as the current active space + void activate() const; - enum class fault_type : uint8_t { - none = 0x00, - present = 0x01, - write = 0x02, - user = 0x04, - reserved = 0x08, - fetch = 0x10 - }; + enum class fault_type : uint8_t { + none = 0x00, + present = 0x01, + write = 0x02, + user = 0x04, + reserved = 0x08, + fetch = 0x10 + }; - /// Allocate pages into virtual memory. May allocate less than requested. - /// \arg virt The virtual address at which to allocate - /// \arg count The number of pages to allocate - /// \arg phys [out] The physical address of the pages allocated - /// \returns The number of pages actually allocated - size_t allocate(uintptr_t virt, size_t count, uintptr_t *phys); + /// Allocate pages into virtual memory. May allocate less than requested. + /// \arg virt The virtual address at which to allocate + /// \arg count The number of pages to allocate + /// \arg phys [out] The physical address of the pages allocated + /// \returns The number of pages actually allocated + size_t allocate(uintptr_t virt, size_t count, uintptr_t *phys); - /// Handle a page fault. - /// \arg addr Address which caused the fault - /// \arg ft Flags from the interrupt about the kind of fault - /// \returns True if the fault was successfully handled - bool handle_fault(uintptr_t addr, fault_type fault); + /// Handle a page fault. + /// \arg addr Address which caused the fault + /// \arg ft Flags from the interrupt about the kind of fault + /// \returns True if the fault was successfully handled + bool handle_fault(uintptr_t addr, fault_type fault); - /// Set up a TCB to operate in this address space. - void initialize_tcb(TCB &tcb); + /// Set up a TCB to operate in this address space. + void initialize_tcb(TCB &tcb); - /// Copy data from one address space to another - /// \arg source The address space data is being copied from - /// \arg dest The address space data is being copied to - /// \arg from Pointer to the data in the source address space - /// \arg to Pointer to the destination in the dest address space - /// \arg length Amount of data to copy, in bytes - /// \returnd The number of bytes copied - static size_t copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length); + /// Copy data from one address space to another + /// \arg source The address space data is being copied from + /// \arg dest The address space data is being copied to + /// \arg from Pointer to the data in the source address space + /// \arg to Pointer to the destination in the dest address space + /// \arg length Amount of data to copy, in bytes + /// \returnd The number of bytes copied + static size_t copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length); private: - friend class vm_area; - friend class vm_mapper_multi; + friend class vm_area; + friend class vm_mapper_multi; - /// Find a given VMA in this address space - bool find_vma(const vm_area &vma, uintptr_t &base) const; + /// Find a given VMA in this address space + bool find_vma(const vm_area &vma, uintptr_t &base) const; - /// Check if a VMA can be resized - bool can_resize(const vm_area &vma, size_t size) const; + /// Check if a VMA can be resized + bool can_resize(const vm_area &vma, size_t size) const; - /// Copy a range of mappings from the given address space - void copy_from(const vm_space &source, const vm_area &vma); + /// Copy a range of mappings from the given address space + void copy_from(const vm_space &source, const vm_area &vma); - bool m_kernel; - page_table *m_pml4; + bool m_kernel; + page_table *m_pml4; - struct area { - uintptr_t base; - vm_area *area; - int compare(const struct area &o) const; - bool operator==(const struct area &o) const; - }; - kutil::vector m_areas; + struct area { + uintptr_t base; + vm_area *area; + int compare(const struct area &o) const; + bool operator==(const struct area &o) const; + }; + kutil::vector m_areas; - kutil::spinlock m_lock; + kutil::spinlock m_lock; }; is_bitfield(vm_space::fault_type); diff --git a/src/libraries/cpu/cpu_id.cpp b/src/libraries/cpu/cpu_id.cpp index dfd4ae0..034c4c2 100644 --- a/src/libraries/cpu/cpu_id.cpp +++ b/src/libraries/cpu/cpu_id.cpp @@ -5,71 +5,71 @@ namespace cpu { inline static void __cpuid( - uint32_t leaf, - uint32_t subleaf, - uint32_t *eax, - uint32_t *ebx = nullptr, - uint32_t *ecx = nullptr, - uint32_t *edx = nullptr) + uint32_t leaf, + uint32_t subleaf, + uint32_t *eax, + uint32_t *ebx = nullptr, + uint32_t *ecx = nullptr, + uint32_t *edx = nullptr) { - uint32_t a, b, c, d; - __asm__ __volatile__ ( "cpuid" - : "=a"(a), "=b"(b), "=c"(c), "=d"(d) - : "a"(leaf), "c"(subleaf) - ); - if (eax) *eax = a; - if (ebx) *ebx = b; - if (ecx) *ecx = c; - if (edx) *edx = d; + uint32_t a, b, c, d; + __asm__ __volatile__ ( "cpuid" + : "=a"(a), "=b"(b), "=c"(c), "=d"(d) + : "a"(leaf), "c"(subleaf) + ); + if (eax) *eax = a; + if (ebx) *ebx = b; + if (ecx) *ecx = c; + if (edx) *edx = d; } cpu_id::cpu_id() : - m_features {0}, - m_missing {0} + m_features {0}, + m_missing {0} { - __cpuid(0, 0, - &m_high_basic, - reinterpret_cast(&m_vendor_id[0]), - reinterpret_cast(&m_vendor_id[8]), - reinterpret_cast(&m_vendor_id[4])); + __cpuid(0, 0, + &m_high_basic, + reinterpret_cast(&m_vendor_id[0]), + reinterpret_cast(&m_vendor_id[8]), + reinterpret_cast(&m_vendor_id[4])); - __cpuid(cpuid_extended, 0, &m_high_ext); + __cpuid(cpuid_extended, 0, &m_high_ext); - if (m_high_ext >= cpuid_extended + 4) { - __cpuid(cpuid_extended + 2, 0, - reinterpret_cast(&m_brand_name[0]), - reinterpret_cast(&m_brand_name[4]), - reinterpret_cast(&m_brand_name[8]), - reinterpret_cast(&m_brand_name[12])); - __cpuid(cpuid_extended + 3, 0, - reinterpret_cast(&m_brand_name[16]), - reinterpret_cast(&m_brand_name[20]), - reinterpret_cast(&m_brand_name[24]), - reinterpret_cast(&m_brand_name[28])); - __cpuid(cpuid_extended + 4, 0, - reinterpret_cast(&m_brand_name[32]), - reinterpret_cast(&m_brand_name[36]), - reinterpret_cast(&m_brand_name[40]), - reinterpret_cast(&m_brand_name[44])); - } else { - m_brand_name[0] = 0; - } + if (m_high_ext >= cpuid_extended + 4) { + __cpuid(cpuid_extended + 2, 0, + reinterpret_cast(&m_brand_name[0]), + reinterpret_cast(&m_brand_name[4]), + reinterpret_cast(&m_brand_name[8]), + reinterpret_cast(&m_brand_name[12])); + __cpuid(cpuid_extended + 3, 0, + reinterpret_cast(&m_brand_name[16]), + reinterpret_cast(&m_brand_name[20]), + reinterpret_cast(&m_brand_name[24]), + reinterpret_cast(&m_brand_name[28])); + __cpuid(cpuid_extended + 4, 0, + reinterpret_cast(&m_brand_name[32]), + reinterpret_cast(&m_brand_name[36]), + reinterpret_cast(&m_brand_name[40]), + reinterpret_cast(&m_brand_name[44])); + } else { + m_brand_name[0] = 0; + } - uint32_t leaf = -1u; - uint32_t sub = -1u; - regs r; + uint32_t leaf = -1u; + uint32_t sub = -1u; + regs r; #define CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit) \ - if (leaf != feat_leaf || sub != feat_sub) { \ - leaf = feat_leaf; sub = feat_sub; r = get(leaf, sub); \ - } \ - if (r.regname & (1ull << bit)) \ - m_features |= (1ull << static_cast(feature::name)); \ + if (leaf != feat_leaf || sub != feat_sub) { \ + leaf = feat_leaf; sub = feat_sub; r = get(leaf, sub); \ + } \ + if (r.regname & (1ull << bit)) \ + m_features |= (1ull << static_cast(feature::name)); \ #define CPU_FEATURE_REQ(name, feat_leaf, feat_sub, regname, bit) \ - CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit); \ - if ((r.regname & (1ull << bit)) == 0) { \ - m_missing |= (1ull << static_cast(feature::name)); \ - } + CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit); \ + if ((r.regname & (1ull << bit)) == 0) { \ + m_missing |= (1ull << static_cast(feature::name)); \ + } #include "cpu/features.inc" #undef CPU_FEATURE_OPT @@ -79,28 +79,28 @@ cpu_id::cpu_id() : cpu_id::regs cpu_id::get(uint32_t leaf, uint32_t sub) const { - regs ret {0, 0, 0, 0}; + regs ret {0, 0, 0, 0}; - if ((leaf & cpuid_extended) == 0 && leaf > m_high_basic) return ret; - if ((leaf & cpuid_extended) != 0 && leaf > m_high_ext) return ret; + if ((leaf & cpuid_extended) == 0 && leaf > m_high_basic) return ret; + if ((leaf & cpuid_extended) != 0 && leaf > m_high_ext) return ret; - __cpuid(leaf, sub, &ret.eax, &ret.ebx, &ret.ecx, &ret.edx); - return ret; + __cpuid(leaf, sub, &ret.eax, &ret.ebx, &ret.ecx, &ret.edx); + return ret; } bool cpu_id::has_feature(feature feat) { - return (m_features & (1 << static_cast(feat))) != 0; + return (m_features & (1 << static_cast(feat))) != 0; } uint8_t cpu_id::local_apic_id() const { - uint32_t eax_unused; - uint32_t ebx; - __cpuid(1, 0, &eax_unused, &ebx); - return static_cast(ebx >> 24); + uint32_t eax_unused; + uint32_t ebx; + __cpuid(1, 0, &eax_unused, &ebx); + return static_cast(ebx >> 24); } } diff --git a/src/libraries/cpu/include/cpu/cpu_id.h b/src/libraries/cpu/include/cpu/cpu_id.h index fa7ccd5..468f525 100644 --- a/src/libraries/cpu/include/cpu/cpu_id.h +++ b/src/libraries/cpu/include/cpu/cpu_id.h @@ -12,73 +12,73 @@ enum class feature { #include "cpu/features.inc" #undef CPU_FEATURE_OPT #undef CPU_FEATURE_REQ - max + max }; class cpu_id { public: - static constexpr uint32_t cpuid_extended = 0x80000000; + static constexpr uint32_t cpuid_extended = 0x80000000; - /// CPUID result register values - struct regs { - union { - uint32_t reg[4]; - uint32_t eax, ebx, ecx, edx; - }; + /// CPUID result register values + struct regs { + union { + uint32_t reg[4]; + uint32_t eax, ebx, ecx, edx; + }; - /// Return true if bit |bit| of EAX is set - bool eax_bit(unsigned bit) { return (eax >> bit) & 0x1; } + /// Return true if bit |bit| of EAX is set + bool eax_bit(unsigned bit) { return (eax >> bit) & 0x1; } - /// Return true if bit |bit| of EBX is set - bool ebx_bit(unsigned bit) { return (ebx >> bit) & 0x1; } + /// Return true if bit |bit| of EBX is set + bool ebx_bit(unsigned bit) { return (ebx >> bit) & 0x1; } - /// Return true if bit |bit| of ECX is set - bool ecx_bit(unsigned bit) { return (ecx >> bit) & 0x1; } + /// Return true if bit |bit| of ECX is set + bool ecx_bit(unsigned bit) { return (ecx >> bit) & 0x1; } - /// Return true if bit |bit| of EDX is set - bool edx_bit(unsigned bit) { return (edx >> bit) & 0x1; } - }; + /// Return true if bit |bit| of EDX is set + bool edx_bit(unsigned bit) { return (edx >> bit) & 0x1; } + }; - cpu_id(); + cpu_id(); - /// The the result of a given CPUID leaf/subleaf - /// \arg leaf The leaf selector (initial EAX) - /// \arg subleaf The subleaf selector (initial ECX) - /// \returns A |regs| struct of the values retuned - regs get(uint32_t leaf, uint32_t sub = 0) const; + /// The the result of a given CPUID leaf/subleaf + /// \arg leaf The leaf selector (initial EAX) + /// \arg subleaf The subleaf selector (initial ECX) + /// \returns A |regs| struct of the values retuned + regs get(uint32_t leaf, uint32_t sub = 0) const; - /// Get the local APIC ID of the current CPU - uint8_t local_apic_id() const; + /// Get the local APIC ID of the current CPU + uint8_t local_apic_id() const; - /// Get the name of the cpu vendor (eg, "GenuineIntel") - inline const char * vendor_id() const { return m_vendor_id; } + /// Get the name of the cpu vendor (eg, "GenuineIntel") + inline const char * vendor_id() const { return m_vendor_id; } - /// Get the brand name of this processor model - inline const char * brand_name() const { return m_brand_name; } + /// Get the brand name of this processor model + inline const char * brand_name() const { return m_brand_name; } - /// Get the highest basic CPUID leaf supported - inline uint32_t highest_basic() const { return m_high_basic; } + /// Get the highest basic CPUID leaf supported + inline uint32_t highest_basic() const { return m_high_basic; } - /// Get the highest extended CPUID leaf supported - inline uint32_t highest_ext() const { return m_high_ext; } + /// Get the highest extended CPUID leaf supported + inline uint32_t highest_ext() const { return m_high_ext; } - /// Get which required options are missing as flags - inline uint64_t missing() const { return m_missing; } + /// Get which required options are missing as flags + inline uint64_t missing() const { return m_missing; } - /// Validate the CPU supports the necessary options for jsix - inline bool supported() const { return m_missing; } + /// Validate the CPU supports the necessary options for jsix + inline bool supported() const { return m_missing; } - /// Return true if the CPU claims to support the given feature - bool has_feature(feature feat); + /// Return true if the CPU claims to support the given feature + bool has_feature(feature feat); private: - uint32_t m_high_basic; - uint32_t m_high_ext; - uint64_t m_features; - uint64_t m_missing; - char m_vendor_id[13]; - char m_brand_name[48]; + uint32_t m_high_basic; + uint32_t m_high_ext; + uint64_t m_features; + uint64_t m_missing; + char m_vendor_id[13]; + char m_brand_name[48]; }; } diff --git a/src/libraries/elf/file.cpp b/src/libraries/elf/file.cpp index e35e151..2aa2870 100644 --- a/src/libraries/elf/file.cpp +++ b/src/libraries/elf/file.cpp @@ -9,36 +9,36 @@ namespace elf { inline const file_header * fh(const void *data) { return reinterpret_cast(data); } file::file(const void *data, size_t size) : - m_programs(offset_ptr(data, fh(data)->ph_offset), fh(data)->ph_entsize, fh(data)->ph_num), - m_sections(offset_ptr(data, fh(data)->sh_offset), fh(data)->sh_entsize, fh(data)->sh_num), - m_data(data), - m_size(size) + m_programs(offset_ptr(data, fh(data)->ph_offset), fh(data)->ph_entsize, fh(data)->ph_num), + m_sections(offset_ptr(data, fh(data)->sh_offset), fh(data)->sh_entsize, fh(data)->sh_num), + m_data(data), + m_size(size) { } bool file::valid() const { - if (m_size < sizeof(file_header)) - return false; + if (m_size < sizeof(file_header)) + return false; - const file_header *fheader = header(); + const file_header *fheader = header(); - return - fheader->magic == expected_magic && - fheader->word_size == wordsize::bits64 && - fheader->endianness == encoding::lsb && - fheader->os_abi == osabi::sysV && - fheader->file_type == filetype::executable && - fheader->machine_type == machine::x64 && - fheader->ident_version == 1 && - fheader->version == 1; + return + fheader->magic == expected_magic && + fheader->word_size == wordsize::bits64 && + fheader->endianness == encoding::lsb && + fheader->os_abi == osabi::sysV && + fheader->file_type == filetype::executable && + fheader->machine_type == machine::x64 && + fheader->ident_version == 1 && + fheader->version == 1; } uintptr_t file::entrypoint() const { - return static_cast(header()->entrypoint); + return static_cast(header()->entrypoint); } diff --git a/src/libraries/elf/include/elf/file.h b/src/libraries/elf/include/elf/file.h index 025f054..87957a8 100644 --- a/src/libraries/elf/include/elf/file.h +++ b/src/libraries/elf/include/elf/file.h @@ -14,62 +14,62 @@ template class subheaders { public: - using iterator = const_offset_iterator; + using iterator = const_offset_iterator; - subheaders(const T *start, size_t size, unsigned count) : - m_start(start), m_size(size), m_count(count) {} + subheaders(const T *start, size_t size, unsigned count) : + m_start(start), m_size(size), m_count(count) {} - inline size_t size() const { return m_size; } - inline unsigned count() const { return m_count; } + inline size_t size() const { return m_size; } + inline unsigned count() const { return m_count; } - inline const T & operator [] (int i) const { return *offset_ptr(m_start, m_size*i); } - inline const iterator begin() const { return iterator(m_start, m_size); } - inline const iterator end() const { return offset_ptr(m_start, m_size*m_count); } + inline const T & operator [] (int i) const { return *offset_ptr(m_start, m_size*i); } + inline const iterator begin() const { return iterator(m_start, m_size); } + inline const iterator end() const { return offset_ptr(m_start, m_size*m_count); } private: - const T *m_start; - size_t m_size; - unsigned m_count; + const T *m_start; + size_t m_size; + unsigned m_count; }; /// Represents a full ELF file's data class file { public: - /// Constructor: Create an elf object out of ELF data in memory - /// \arg data The ELF data to read - /// \arg size Size of the ELF data, in bytes - file(const void *data, size_t size); + /// Constructor: Create an elf object out of ELF data in memory + /// \arg data The ELF data to read + /// \arg size Size of the ELF data, in bytes + file(const void *data, size_t size); - /// Check the validity of the ELF data - /// \returns true for valid ELF data - bool valid() const; + /// Check the validity of the ELF data + /// \returns true for valid ELF data + bool valid() const; - /// Get the entrypoint address of the program image - /// \returns A pointer to the entrypoint of the program - uintptr_t entrypoint() const; + /// Get the entrypoint address of the program image + /// \returns A pointer to the entrypoint of the program + uintptr_t entrypoint() const; - /// Get the base address of the program in memory - inline uintptr_t base() const { - return reinterpret_cast(m_data); - } + /// Get the base address of the program in memory + inline uintptr_t base() const { + return reinterpret_cast(m_data); + } - /// Get the ELF program headers - inline const subheaders & programs() const { return m_programs; } + /// Get the ELF program headers + inline const subheaders & programs() const { return m_programs; } - /// Get the ELF section headers - inline const subheaders & sections() const { return m_sections; } + /// Get the ELF section headers + inline const subheaders & sections() const { return m_sections; } - inline const file_header * header() const { - return reinterpret_cast(m_data); - } + inline const file_header * header() const { + return reinterpret_cast(m_data); + } private: - subheaders m_programs; - subheaders m_sections; + subheaders m_programs; + subheaders m_sections; - const void *m_data; - size_t m_size; + const void *m_data; + size_t m_size; }; } diff --git a/src/libraries/elf/include/elf/headers.h b/src/libraries/elf/include/elf/headers.h index f1aa400..a1c9c47 100644 --- a/src/libraries/elf/include/elf/headers.h +++ b/src/libraries/elf/include/elf/headers.h @@ -11,45 +11,45 @@ enum class machine : uint16_t { none, x64 = 0x3e }; enum class filetype : uint16_t { - none, - relocatable, - executable, - shared, - core + none, + relocatable, + executable, + shared, + core }; struct file_header { - uint32_t magic; + uint32_t magic; - wordsize word_size; - encoding endianness; - uint8_t ident_version; - osabi os_abi; + wordsize word_size; + encoding endianness; + uint8_t ident_version; + osabi os_abi; - uint64_t reserved; + uint64_t reserved; - filetype file_type; - machine machine_type; + filetype file_type; + machine machine_type; - uint32_t version; + uint32_t version; - uint64_t entrypoint; - uint64_t ph_offset; - uint64_t sh_offset; + uint64_t entrypoint; + uint64_t ph_offset; + uint64_t sh_offset; - uint32_t flags; + uint32_t flags; - uint16_t eh_size; + uint16_t eh_size; - uint16_t ph_entsize; - uint16_t ph_num; + uint16_t ph_entsize; + uint16_t ph_num; - uint16_t sh_entsize; - uint16_t sh_num; + uint16_t sh_entsize; + uint16_t sh_num; - uint16_t sh_str_idx; + uint16_t sh_str_idx; } __attribute__ ((packed)); @@ -57,40 +57,40 @@ enum class segment_type : uint32_t { null, load, dynamic, interpreter, note }; struct program_header { - segment_type type; - uint32_t flags; - uint64_t offset; + segment_type type; + uint32_t flags; + uint64_t offset; - uint64_t vaddr; - uint64_t paddr; + uint64_t vaddr; + uint64_t paddr; - uint64_t file_size; - uint64_t mem_size; + uint64_t file_size; + uint64_t mem_size; - uint64_t align; + uint64_t align; } __attribute__ ((packed)); enum class section_type : uint32_t { null, progbits }; enum class section_flags : uint64_t { - write = 0x01, - alloc = 0x02, - exec = 0x04, + write = 0x01, + alloc = 0x02, + exec = 0x04, }; struct section_header { - uint32_t name_offset; - section_type type; - section_flags flags; - uint64_t addr; - uint64_t offset; - uint64_t size; - uint32_t link; - uint32_t info; - uint64_t align; - uint64_t entry_size; + uint32_t name_offset; + section_type type; + section_flags flags; + uint64_t addr; + uint64_t offset; + uint64_t size; + uint32_t link; + uint32_t info; + uint64_t align; + uint64_t entry_size; } __attribute__ ((packed)); } // namespace elf diff --git a/src/libraries/j6/init.cpp b/src/libraries/j6/init.cpp index 21309a5..d73ae2a 100644 --- a/src/libraries/j6/init.cpp +++ b/src/libraries/j6/init.cpp @@ -11,31 +11,31 @@ j6_handle_t __handle_self = j6_handle_invalid; extern "C" void _get_init(size_t *initc, struct j6_init_value **initv) { - if (!initc) - return; + if (!initc) + return; - *initc = __initc; - if (initv) - *initv = __initv; + *initc = __initc; + if (initv) + *initv = __initv; } extern "C" void _init_libj6(uint64_t *rsp) { - uint64_t argc = *rsp++; - rsp += argc; + uint64_t argc = *rsp++; + rsp += argc; - __initc = *rsp++; - __initv = (struct j6_init_value *)rsp; + __initc = *rsp++; + __initv = (struct j6_init_value *)rsp; - for (unsigned i = 0; i < __initc; ++i) { - if (__initv[i].type == j6_init_handle_other && - __initv[i].handle.type == j6_object_type_system) { - __handle_sys = __initv[i].handle.handle; - } - else if (__initv[i].type == j6_init_handle_self && - __initv[i].handle.type == j6_object_type_process) { - __handle_self = __initv[i].handle.handle; - } - } + for (unsigned i = 0; i < __initc; ++i) { + if (__initv[i].type == j6_init_handle_other && + __initv[i].handle.type == j6_object_type_system) { + __handle_sys = __initv[i].handle.handle; + } + else if (__initv[i].type == j6_init_handle_self && + __initv[i].handle.type == j6_object_type_process) { + __handle_self = __initv[i].handle.handle; + } + } } diff --git a/src/libraries/kutil/bip_buffer.cpp b/src/libraries/kutil/bip_buffer.cpp index ec7afbe..0433771 100644 --- a/src/libraries/kutil/bip_buffer.cpp +++ b/src/libraries/kutil/bip_buffer.cpp @@ -4,94 +4,94 @@ namespace kutil { bip_buffer::bip_buffer() : - m_start_a(0), - m_start_b(0), - m_size_a(0), - m_size_b(0), - m_size_r(0), - m_buffer_size(0), - m_buffer(nullptr) - {} + m_start_a(0), + m_start_b(0), + m_size_a(0), + m_size_b(0), + m_size_r(0), + m_buffer_size(0), + m_buffer(nullptr) + {} bip_buffer::bip_buffer(uint8_t *buffer, size_t size) : - m_start_a(0), - m_start_b(0), - m_size_a(0), - m_size_b(0), - m_size_r(0), - m_buffer_size(size), - m_buffer(buffer) - {} + m_start_a(0), + m_start_b(0), + m_size_a(0), + m_size_b(0), + m_size_r(0), + m_buffer_size(size), + m_buffer(buffer) + {} size_t bip_buffer::reserve(size_t size, void **area) { - if (m_size_r) { - *area = nullptr; - return 0; - } + if (m_size_r) { + *area = nullptr; + return 0; + } - size_t remaining = 0; - if (m_size_b) { - // If B exists, we're appending there. Get space between - // the end of B and start of A. - remaining = m_start_a - m_start_b - m_size_b; - m_start_r = m_start_b + m_size_b; - } else { - // B doesn't exist, check the space both before and after A. - // If the end of A has enough room for this write, put it there. - remaining = m_buffer_size - m_start_a - m_size_a; - m_start_r = m_start_a + m_size_a; + size_t remaining = 0; + if (m_size_b) { + // If B exists, we're appending there. Get space between + // the end of B and start of A. + remaining = m_start_a - m_start_b - m_size_b; + m_start_r = m_start_b + m_size_b; + } else { + // B doesn't exist, check the space both before and after A. + // If the end of A has enough room for this write, put it there. + remaining = m_buffer_size - m_start_a - m_size_a; + m_start_r = m_start_a + m_size_a; - // Otherwise use the bigger of the areas in front of and after A - if (remaining < size && m_start_a > remaining) { - remaining = m_start_a; - m_start_r = 0; - } - } + // Otherwise use the bigger of the areas in front of and after A + if (remaining < size && m_start_a > remaining) { + remaining = m_start_a; + m_start_r = 0; + } + } - if (!remaining) { - *area = nullptr; - return 0; - } + if (!remaining) { + *area = nullptr; + return 0; + } - m_size_r = (remaining < size) ? remaining : size; - *area = &m_buffer[m_start_r]; - return m_size_r; + m_size_r = (remaining < size) ? remaining : size; + *area = &m_buffer[m_start_r]; + return m_size_r; } void bip_buffer::commit(size_t size) { - kassert(size <= m_size_r, "Tried to commit more than reserved"); + kassert(size <= m_size_r, "Tried to commit more than reserved"); - if (m_start_r == m_start_a + m_size_a) { - // We were adding to A - m_size_a += size; - } else { - // We were adding to B - kassert(m_start_r == m_start_b + m_size_b, "Bad m_start_r!"); - m_size_b += size; - } + if (m_start_r == m_start_a + m_size_a) { + // We were adding to A + m_size_a += size; + } else { + // We were adding to B + kassert(m_start_r == m_start_b + m_size_b, "Bad m_start_r!"); + m_size_b += size; + } - m_start_r = m_size_r = 0; + m_start_r = m_size_r = 0; } size_t bip_buffer::get_block(void **area) const { - *area = m_size_a ? &m_buffer[m_start_a] : nullptr; - return m_size_a; + *area = m_size_a ? &m_buffer[m_start_a] : nullptr; + return m_size_a; } void bip_buffer::consume(size_t size) { - kassert(size <= m_size_a, "Consumed more bytes than exist in A"); - if (size >= m_size_a) { - m_size_a = m_size_b; - m_start_a = m_start_b; - m_size_b = m_start_b = 0; - } else { - m_size_a -= size; - m_start_a += size; - } + kassert(size <= m_size_a, "Consumed more bytes than exist in A"); + if (size >= m_size_a) { + m_size_a = m_size_b; + m_start_a = m_start_b; + m_size_b = m_start_b = 0; + } else { + m_size_a -= size; + m_start_a += size; + } } } // namespace kutil diff --git a/src/libraries/kutil/heap_allocator.cpp b/src/libraries/kutil/heap_allocator.cpp index 01b9506..a7aef70 100644 --- a/src/libraries/kutil/heap_allocator.cpp +++ b/src/libraries/kutil/heap_allocator.cpp @@ -8,172 +8,172 @@ namespace kutil { struct heap_allocator::mem_header { - mem_header(mem_header *prev, mem_header *next, uint8_t order) : - m_prev(prev), m_next(next) - { - set_order(order); - } + mem_header(mem_header *prev, mem_header *next, uint8_t order) : + m_prev(prev), m_next(next) + { + set_order(order); + } - inline void set_order(uint8_t order) { - m_prev = reinterpret_cast( - reinterpret_cast(prev()) | (order & 0x3f)); - } + inline void set_order(uint8_t order) { + m_prev = reinterpret_cast( + reinterpret_cast(prev()) | (order & 0x3f)); + } - inline void set_used(bool used) { - m_next = reinterpret_cast( - reinterpret_cast(next()) | (used ? 1 : 0)); - } + inline void set_used(bool used) { + m_next = reinterpret_cast( + reinterpret_cast(next()) | (used ? 1 : 0)); + } - inline void set_next(mem_header *next) { - bool u = used(); - m_next = next; - set_used(u); - } + inline void set_next(mem_header *next) { + bool u = used(); + m_next = next; + set_used(u); + } - inline void set_prev(mem_header *prev) { - uint8_t s = order(); - m_prev = prev; - set_order(s); - } + inline void set_prev(mem_header *prev) { + uint8_t s = order(); + m_prev = prev; + set_order(s); + } - void remove() { - if (next()) next()->set_prev(prev()); - if (prev()) prev()->set_next(next()); - set_prev(nullptr); - set_next(nullptr); - } + void remove() { + if (next()) next()->set_prev(prev()); + if (prev()) prev()->set_next(next()); + set_prev(nullptr); + set_next(nullptr); + } - inline mem_header * next() { return kutil::mask_pointer(m_next, 0x3f); } - inline mem_header * prev() { return kutil::mask_pointer(m_prev, 0x3f); } + inline mem_header * next() { return kutil::mask_pointer(m_next, 0x3f); } + inline mem_header * prev() { return kutil::mask_pointer(m_prev, 0x3f); } - inline mem_header * buddy() const { - return reinterpret_cast( - reinterpret_cast(this) ^ (1 << order())); - } + inline mem_header * buddy() const { + return reinterpret_cast( + reinterpret_cast(this) ^ (1 << order())); + } - inline bool eldest() const { return this < buddy(); } + inline bool eldest() const { return this < buddy(); } - inline uint8_t order() const { return reinterpret_cast(m_prev) & 0x3f; } - inline bool used() const { return reinterpret_cast(m_next) & 0x1; } + inline uint8_t order() const { return reinterpret_cast(m_prev) & 0x3f; } + inline bool used() const { return reinterpret_cast(m_next) & 0x1; } private: - mem_header *m_prev; - mem_header *m_next; + mem_header *m_prev; + mem_header *m_next; }; heap_allocator::heap_allocator() : m_start {0}, m_end {0} {} heap_allocator::heap_allocator(uintptr_t start, size_t size) : - m_start {start}, - m_end {start+size}, - m_blocks {0}, - m_allocated_size {0} + m_start {start}, + m_end {start+size}, + m_blocks {0}, + m_allocated_size {0} { - kutil::memset(m_free, 0, sizeof(m_free)); + kutil::memset(m_free, 0, sizeof(m_free)); } void * heap_allocator::allocate(size_t length) { - size_t total = length + sizeof(mem_header); + size_t total = length + sizeof(mem_header); - if (length == 0) - return nullptr; + if (length == 0) + return nullptr; - unsigned order = log2(total); - if (order < min_order) - order = min_order; + unsigned order = log2(total); + if (order < min_order) + order = min_order; - kassert(order <= max_order, "Tried to allocate a block bigger than max_order"); - if (order > max_order) - return nullptr; + kassert(order <= max_order, "Tried to allocate a block bigger than max_order"); + if (order > max_order) + return nullptr; - scoped_lock lock {m_lock}; + scoped_lock lock {m_lock}; - mem_header *header = pop_free(order); - header->set_used(true); - m_allocated_size += (1 << order); - return header + 1; + mem_header *header = pop_free(order); + header->set_used(true); + m_allocated_size += (1 << order); + return header + 1; } void heap_allocator::free(void *p) { - if (!p) return; + if (!p) return; - uintptr_t addr = reinterpret_cast(p); - kassert(addr >= m_start && addr < m_end, - "Attempt to free non-heap pointer"); + uintptr_t addr = reinterpret_cast(p); + kassert(addr >= m_start && addr < m_end, + "Attempt to free non-heap pointer"); - scoped_lock lock {m_lock}; + scoped_lock lock {m_lock}; - mem_header *header = reinterpret_cast(p); - header -= 1; // p points after the header - header->set_used(false); - m_allocated_size -= (1 << header->order()); + mem_header *header = reinterpret_cast(p); + header -= 1; // p points after the header + header->set_used(false); + m_allocated_size -= (1 << header->order()); - while (header->order() != max_order) { - auto order = header->order(); + while (header->order() != max_order) { + auto order = header->order(); - mem_header *buddy = header->buddy(); - if (buddy->used() || buddy->order() != order) - break; + mem_header *buddy = header->buddy(); + if (buddy->used() || buddy->order() != order) + break; - if (get_free(order) == buddy) - get_free(order) = buddy->next(); + if (get_free(order) == buddy) + get_free(order) = buddy->next(); - buddy->remove(); + buddy->remove(); - header = header->eldest() ? header : buddy; - header->set_order(order + 1); - } + header = header->eldest() ? header : buddy; + header->set_order(order + 1); + } - uint8_t order = header->order(); - header->set_next(get_free(order)); - get_free(order) = header; - if (header->next()) - header->next()->set_prev(header); + uint8_t order = header->order(); + header->set_next(get_free(order)); + get_free(order) = header; + if (header->next()) + header->next()->set_prev(header); } void heap_allocator::ensure_block(unsigned order) { - if (get_free(order) != nullptr) - return; + if (get_free(order) != nullptr) + return; - if (order == max_order) { - size_t bytes = (1 << max_order); - uintptr_t next = m_start + m_blocks * bytes; - if (next + bytes <= m_end) { - mem_header *nextp = reinterpret_cast(next); - new (nextp) mem_header(nullptr, nullptr, order); - get_free(order) = nextp; - ++m_blocks; - } - } else { - mem_header *orig = pop_free(order + 1); - if (orig) { - mem_header *next = kutil::offset_pointer(orig, 1 << order); - new (next) mem_header(orig, nullptr, order); + if (order == max_order) { + size_t bytes = (1 << max_order); + uintptr_t next = m_start + m_blocks * bytes; + if (next + bytes <= m_end) { + mem_header *nextp = reinterpret_cast(next); + new (nextp) mem_header(nullptr, nullptr, order); + get_free(order) = nextp; + ++m_blocks; + } + } else { + mem_header *orig = pop_free(order + 1); + if (orig) { + mem_header *next = kutil::offset_pointer(orig, 1 << order); + new (next) mem_header(orig, nullptr, order); - orig->set_next(next); - orig->set_order(order); - get_free(order) = orig; - } - } + orig->set_next(next); + orig->set_order(order); + get_free(order) = orig; + } + } } heap_allocator::mem_header * heap_allocator::pop_free(unsigned order) { - ensure_block(order); - mem_header *block = get_free(order); - if (block) { - get_free(order) = block->next(); - block->remove(); - } - return block; + ensure_block(order); + mem_header *block = get_free(order); + if (block) { + get_free(order) = block->next(); + block->remove(); + } + return block; } } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/avl_tree.h b/src/libraries/kutil/include/kutil/avl_tree.h index 71264dc..17da833 100644 --- a/src/libraries/kutil/include/kutil/avl_tree.h +++ b/src/libraries/kutil/include/kutil/avl_tree.h @@ -14,238 +14,238 @@ template class avl_tree; /// A node in a `avl_tree` template class avl_node : - public T, - public slab_allocated> + public T, + public slab_allocated> { public: - using item_type = T; - using node_type = avl_node; + using item_type = T; + using node_type = avl_node; - /// Dereference operator. Helper to cast this node to the contained type. - /// \returns A pointer to the node, cast to T*. - inline item_type & operator*() { return *this; } + /// Dereference operator. Helper to cast this node to the contained type. + /// \returns A pointer to the node, cast to T*. + inline item_type & operator*() { return *this; } - /// Dereference operator. Helper to cast this node to the contained type. - /// \returns A pointer to the node, cast to T*. - inline const item_type & operator*() const { return *this; } + /// Dereference operator. Helper to cast this node to the contained type. + /// \returns A pointer to the node, cast to T*. + inline const item_type & operator*() const { return *this; } - /// Cast operator. Helper to cast this node to the contained type. - /// \returns A reference to the node, cast to T&. - inline operator item_type& () { return *this; } + /// Cast operator. Helper to cast this node to the contained type. + /// \returns A reference to the node, cast to T&. + inline operator item_type& () { return *this; } - /// Cast operator. Helper to cast this node to the contained type. - /// \returns A reference to the node, cast to const T&. - inline operator const item_type& () { return *this; } + /// Cast operator. Helper to cast this node to the contained type. + /// \returns A reference to the node, cast to const T&. + inline operator const item_type& () { return *this; } - /// Helper to cast this node to the contained type. - /// \returns A reference to the node, cast to const T&. - inline const item_type& item() const { return *this; } + /// Helper to cast this node to the contained type. + /// \returns A reference to the node, cast to const T&. + inline const item_type& item() const { return *this; } - /// Helper to cast this node to the contained type. - /// \returns A reference to the node, cast to T&. - inline item_type& item() { return *this; } + /// Helper to cast this node to the contained type. + /// \returns A reference to the node, cast to T&. + inline item_type& item() { return *this; } - /// Accessor for the left child. - /// \returns A pointer to the left child, or nullptr. - inline node_type * left() { return m_left; } + /// Accessor for the left child. + /// \returns A pointer to the left child, or nullptr. + inline node_type * left() { return m_left; } - /// Accessor for the left child. - /// \returns A pointer to the left child, or nullptr. - inline const node_type * left() const { return m_left; } + /// Accessor for the left child. + /// \returns A pointer to the left child, or nullptr. + inline const node_type * left() const { return m_left; } - /// Accessor for the right child. - /// \returns A pointer to the right child, or nullptr. - inline node_type * right() { return m_right; } + /// Accessor for the right child. + /// \returns A pointer to the right child, or nullptr. + inline node_type * right() { return m_right; } - /// Accessor for the right child. - /// \returns A pointer to the right child, or nullptr. - inline const node_type * right() const { return m_right; } + /// Accessor for the right child. + /// \returns A pointer to the right child, or nullptr. + inline const node_type * right() const { return m_right; } private: - friend class avl_tree; + friend class avl_tree; - inline static int height(node_type *l) { return (l ? l->m_height : 0); } + inline static int height(node_type *l) { return (l ? l->m_height : 0); } - // Update this node's height and return its new balance factor - inline int update_height() - { - int left = height(m_left); - int right = height(m_right); - m_height = left > right ? left : right; - return left - right; - } + // Update this node's height and return its new balance factor + inline int update_height() + { + int left = height(m_left); + int right = height(m_right); + m_height = left > right ? left : right; + return left - right; + } - int bias(node_type *addend) - { - const item_type &this_item = *this; - const item_type &that_item = *addend; - if (that_item < this_item) - return -1; - else if (that_item > this_item) - return 1; + int bias(node_type *addend) + { + const item_type &this_item = *this; + const item_type &that_item = *addend; + if (that_item < this_item) + return -1; + else if (that_item > this_item) + return 1; - kassert(false, "Equal items not allowed in AVL tree"); - return 0; - } + kassert(false, "Equal items not allowed in AVL tree"); + return 0; + } - static node_type * rotate_right(node_type *existing) - { - node_type *root = existing->m_left; - node_type *left = root->m_right; + static node_type * rotate_right(node_type *existing) + { + node_type *root = existing->m_left; + node_type *left = root->m_right; - root->m_right = existing; - existing->m_left = left; + root->m_right = existing; + existing->m_left = left; - existing->update_height(); - root->update_height(); + existing->update_height(); + root->update_height(); - return root; - } + return root; + } - static node_type * rotate_left(node_type *existing) - { - node_type *root = existing->m_right; - node_type *right = root->m_left; + static node_type * rotate_left(node_type *existing) + { + node_type *root = existing->m_right; + node_type *right = root->m_left; - root->m_left = existing; - existing->m_right = right; + root->m_left = existing; + existing->m_right = right; - existing->update_height(); - root->update_height(); + existing->update_height(); + root->update_height(); - return root; - } + return root; + } - static node_type * insert(node_type *existing, node_type *addend) - { - if (existing == nullptr) - return addend; + static node_type * insert(node_type *existing, node_type *addend) + { + if (existing == nullptr) + return addend; - if (existing->compare(addend) < 0) - existing->m_left = insert(existing->m_left, addend); - else - existing->m_right = insert(existing->m_right, addend); + if (existing->compare(addend) < 0) + existing->m_left = insert(existing->m_left, addend); + else + existing->m_right = insert(existing->m_right, addend); - int balance = existing->update_height(); - if (balance > 1) { - // Left-heavy - if (existing->m_left->compare(addend) < 0) { - // Left Left - return rotate_right(existing); - } else { - // Left Right - existing->m_left = rotate_left(existing->m_left); - return rotate_right(existing); - } - } else if (balance < -1) { - // Right-heavy - if (existing->m_right->compare(addend) > 0) { - // Right Right - return rotate_left(existing); - } else { - // Right Left - existing->m_right = rotate_right(existing->m_right); - return rotate_left(existing); - } - } + int balance = existing->update_height(); + if (balance > 1) { + // Left-heavy + if (existing->m_left->compare(addend) < 0) { + // Left Left + return rotate_right(existing); + } else { + // Left Right + existing->m_left = rotate_left(existing->m_left); + return rotate_right(existing); + } + } else if (balance < -1) { + // Right-heavy + if (existing->m_right->compare(addend) > 0) { + // Right Right + return rotate_left(existing); + } else { + // Right Left + existing->m_right = rotate_right(existing->m_right); + return rotate_left(existing); + } + } - return existing; - } + return existing; + } - static node_type * remove(node_type *existing, node_type *subtrahend) - { - if (existing == nullptr) - return existing; + static node_type * remove(node_type *existing, node_type *subtrahend) + { + if (existing == nullptr) + return existing; - if (existing == subtrahend) { - if (!existing->m_left || !existing->m_right) { - // At least one child is null - node_type *temp = existing->m_left ? - existing->m_left : existing->m_right; + if (existing == subtrahend) { + if (!existing->m_left || !existing->m_right) { + // At least one child is null + node_type *temp = existing->m_left ? + existing->m_left : existing->m_right; - if (temp == nullptr) { - // Both were null - temp = existing; - existing = nullptr; - } else { - *existing = *temp; - } + if (temp == nullptr) { + // Both were null + temp = existing; + existing = nullptr; + } else { + *existing = *temp; + } - delete temp; - } else { - // Both children exist, find next node - node_type *temp = existing->m_right; - while (temp->m_left) - temp = temp->m_left; + delete temp; + } else { + // Both children exist, find next node + node_type *temp = existing->m_right; + while (temp->m_left) + temp = temp->m_left; - *existing = *temp; - existing->m_right = remove(existing->m_right, temp); - } - } else if (existing->compare(subtrahend) < 0) { - existing->m_left = remove(existing->m_left, subtrahend); - } else { - existing->m_right = remove(existing->m_right, subtrahend); - } + *existing = *temp; + existing->m_right = remove(existing->m_right, temp); + } + } else if (existing->compare(subtrahend) < 0) { + existing->m_left = remove(existing->m_left, subtrahend); + } else { + existing->m_right = remove(existing->m_right, subtrahend); + } - if (!existing) - return nullptr; + if (!existing) + return nullptr; - int balance = existing->update_height(); - if (balance > 1) { - int left_balance = existing->m_left->update_height(); + int balance = existing->update_height(); + if (balance > 1) { + int left_balance = existing->m_left->update_height(); - if (left_balance < 0) - existing->m_left = rotate_left(existing->m_left); + if (left_balance < 0) + existing->m_left = rotate_left(existing->m_left); - return rotate_right(existing); - } else if (balance < -1) { - int right_balance = existing->m_right->update_height(); + return rotate_right(existing); + } else if (balance < -1) { + int right_balance = existing->m_right->update_height(); - if (right_balance > 0) - existing->m_right = rotate_right(existing->m_right); + if (right_balance > 0) + existing->m_right = rotate_right(existing->m_right); - return rotate_left(existing); - } + return rotate_left(existing); + } - return existing; - } + return existing; + } - int m_height; - node_type *m_left; - node_type *m_right; + int m_height; + node_type *m_left; + node_type *m_right; }; template class avl_tree { public: - using item_type = T; - using node_type = avl_node; + using item_type = T; + using node_type = avl_node; - avl_tree() = default; - avl_tree(avl_tree &&other) : - m_count(other.m_count), m_root(other.m_root) - { - other.m_root = nullptr; - other.m_count = 0; - } + avl_tree() = default; + avl_tree(avl_tree &&other) : + m_count(other.m_count), m_root(other.m_root) + { + other.m_root = nullptr; + other.m_count = 0; + } - inline node_type * root() { return m_root; } - inline unsigned count() const { return m_count; } + inline node_type * root() { return m_root; } + inline unsigned count() const { return m_count; } - inline void remove(node_type *subtrahend) { - m_root = node_type::remove(m_root, subtrahend); - m_count--; - } + inline void remove(node_type *subtrahend) { + m_root = node_type::remove(m_root, subtrahend); + m_count--; + } - inline void insert(node_type *addend) { - m_root = node_type::insert(m_root, addend); - m_count++; - } + inline void insert(node_type *addend) { + m_root = node_type::insert(m_root, addend); + m_count++; + } private: - unsigned m_count {0}; - node_type *m_root {nullptr}; + unsigned m_count {0}; + node_type *m_root {nullptr}; }; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/bip_buffer.h b/src/libraries/kutil/include/kutil/bip_buffer.h index f2d55db..c178cea 100644 --- a/src/libraries/kutil/include/kutil/bip_buffer.h +++ b/src/libraries/kutil/include/kutil/bip_buffer.h @@ -11,49 +11,49 @@ namespace kutil { class bip_buffer { public: - /// Default constructor. Creates a zero-size buffer. - bip_buffer(); + /// Default constructor. Creates a zero-size buffer. + bip_buffer(); - /// Constructor. - bip_buffer(uint8_t *buffer, size_t size); + /// Constructor. + bip_buffer(uint8_t *buffer, size_t size); - /// Reserve an area of buffer for a write. - /// \arg size Requested size, in bytes - /// \arg area [out] Pointer to returned area - /// \returns Size of returned area, in bytes, or 0 on failure - size_t reserve(size_t size, void **area); + /// Reserve an area of buffer for a write. + /// \arg size Requested size, in bytes + /// \arg area [out] Pointer to returned area + /// \returns Size of returned area, in bytes, or 0 on failure + size_t reserve(size_t size, void **area); - /// Commit a pending write started by reserve() - /// \arg size Amount of data used, in bytes - void commit(size_t size); + /// Commit a pending write started by reserve() + /// \arg size Amount of data used, in bytes + void commit(size_t size); - /// Get a pointer to a block of data in the buffer. - /// \arg area [out] Pointer to the retuned area - /// \returns Size of the returned area, in bytes - size_t get_block(void **area) const; + /// Get a pointer to a block of data in the buffer. + /// \arg area [out] Pointer to the retuned area + /// \returns Size of the returned area, in bytes + size_t get_block(void **area) const; - /// Mark a number of bytes as consumed, freeing buffer space - /// \arg size Number of bytes to consume - void consume(size_t size); + /// Mark a number of bytes as consumed, freeing buffer space + /// \arg size Number of bytes to consume + void consume(size_t size); - /// Get total amount of data in the buffer. - /// \returns Number of bytes committed to the buffer - inline size_t size() const { return m_size_a + m_size_b; } + /// Get total amount of data in the buffer. + /// \returns Number of bytes committed to the buffer + inline size_t size() const { return m_size_a + m_size_b; } - /// Get total amount of free buffer remaining - /// \returns Number of bytes of buffer that are free - inline size_t free_space() const { return m_buffer_size - size(); } + /// Get total amount of free buffer remaining + /// \returns Number of bytes of buffer that are free + inline size_t free_space() const { return m_buffer_size - size(); } private: - size_t m_start_a; - size_t m_start_b; - size_t m_start_r; - size_t m_size_a; - size_t m_size_b; - size_t m_size_r; + size_t m_start_a; + size_t m_start_b; + size_t m_start_r; + size_t m_size_a; + size_t m_size_b; + size_t m_size_r; - const size_t m_buffer_size; - uint8_t * const m_buffer; + const size_t m_buffer_size; + uint8_t * const m_buffer; }; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/constexpr_hash.h b/src/libraries/kutil/include/kutil/constexpr_hash.h index c4572e0..54caac7 100644 --- a/src/libraries/kutil/include/kutil/constexpr_hash.h +++ b/src/libraries/kutil/include/kutil/constexpr_hash.h @@ -8,35 +8,35 @@ namespace kutil { constexpr static const uint8_t pearson_hash_table[256] = { - 0x76,0x07,0xbe,0x47,0xcf,0x41,0x0a,0xe8,0x01,0x5c,0x9f,0xc5,0x24,0x63,0x9a,0x85, - 0x39,0x2c,0xe2,0x34,0xb9,0xf2,0xae,0x40,0x10,0x90,0x94,0xd1,0x98,0x2d,0x16,0xfd, - 0xc6,0x48,0x0d,0xce,0x74,0x43,0x28,0xf9,0x61,0x12,0xd0,0xcd,0xd8,0xd7,0xa8,0x78, - 0x73,0x70,0xcc,0x1e,0x17,0xa7,0x87,0x38,0x68,0x91,0xc1,0x04,0x3f,0xf5,0xde,0xa3, - 0x8a,0xe5,0x9b,0xec,0x97,0xd5,0x71,0x4a,0x20,0xca,0xc8,0xc4,0x83,0x53,0xe7,0x7b, - 0x64,0x31,0x06,0xe0,0x7a,0xb6,0x52,0x8c,0xba,0x58,0xcb,0xb5,0x37,0x51,0x59,0xa1, - 0x11,0xe3,0x5a,0xdb,0xe1,0x6d,0x46,0x62,0xaf,0xbd,0x57,0xb8,0x0e,0xf4,0xdd,0xa6, - 0x45,0xf8,0x35,0x42,0x56,0xdf,0xad,0x80,0xb2,0x0b,0x5b,0xd4,0x86,0xb3,0xf0,0xc9, - 0x3c,0xa5,0xc0,0x8e,0x55,0x77,0xeb,0x36,0x79,0xab,0x4c,0x25,0xed,0xa9,0x75,0x8f, - 0xee,0xc2,0x72,0x8b,0x60,0x2a,0xfa,0x32,0xe9,0xda,0x03,0x1b,0x27,0x69,0x18,0x9e, - 0x88,0x96,0x54,0x81,0x30,0x22,0x7c,0x4f,0xc7,0xef,0x5d,0xa4,0x67,0x44,0xc3,0x99, - 0xbb,0xd3,0x8d,0x65,0xb1,0x82,0x09,0x1a,0x13,0xd9,0x9c,0x4d,0xb0,0xfc,0xac,0xbc, - 0x6a,0x29,0x95,0x19,0x92,0xaa,0x49,0x7d,0x3b,0xfb,0x50,0xb7,0xf3,0x5e,0x3e,0x6b, - 0x3a,0x14,0x2b,0xb4,0xfe,0xe6,0x93,0x23,0xd6,0x1f,0xd2,0x0c,0x1d,0x9d,0x6c,0x66, - 0x1c,0x89,0xbf,0xf6,0xff,0x6f,0x84,0x6e,0x2e,0xea,0x21,0xf7,0x7f,0x33,0xf1,0xe4, - 0x3d,0x0f,0x05,0x08,0x4e,0xa2,0xa0,0x2f,0xdc,0x00,0x5f,0x15,0x7e,0x02,0x4b,0x26 + 0x76,0x07,0xbe,0x47,0xcf,0x41,0x0a,0xe8,0x01,0x5c,0x9f,0xc5,0x24,0x63,0x9a,0x85, + 0x39,0x2c,0xe2,0x34,0xb9,0xf2,0xae,0x40,0x10,0x90,0x94,0xd1,0x98,0x2d,0x16,0xfd, + 0xc6,0x48,0x0d,0xce,0x74,0x43,0x28,0xf9,0x61,0x12,0xd0,0xcd,0xd8,0xd7,0xa8,0x78, + 0x73,0x70,0xcc,0x1e,0x17,0xa7,0x87,0x38,0x68,0x91,0xc1,0x04,0x3f,0xf5,0xde,0xa3, + 0x8a,0xe5,0x9b,0xec,0x97,0xd5,0x71,0x4a,0x20,0xca,0xc8,0xc4,0x83,0x53,0xe7,0x7b, + 0x64,0x31,0x06,0xe0,0x7a,0xb6,0x52,0x8c,0xba,0x58,0xcb,0xb5,0x37,0x51,0x59,0xa1, + 0x11,0xe3,0x5a,0xdb,0xe1,0x6d,0x46,0x62,0xaf,0xbd,0x57,0xb8,0x0e,0xf4,0xdd,0xa6, + 0x45,0xf8,0x35,0x42,0x56,0xdf,0xad,0x80,0xb2,0x0b,0x5b,0xd4,0x86,0xb3,0xf0,0xc9, + 0x3c,0xa5,0xc0,0x8e,0x55,0x77,0xeb,0x36,0x79,0xab,0x4c,0x25,0xed,0xa9,0x75,0x8f, + 0xee,0xc2,0x72,0x8b,0x60,0x2a,0xfa,0x32,0xe9,0xda,0x03,0x1b,0x27,0x69,0x18,0x9e, + 0x88,0x96,0x54,0x81,0x30,0x22,0x7c,0x4f,0xc7,0xef,0x5d,0xa4,0x67,0x44,0xc3,0x99, + 0xbb,0xd3,0x8d,0x65,0xb1,0x82,0x09,0x1a,0x13,0xd9,0x9c,0x4d,0xb0,0xfc,0xac,0xbc, + 0x6a,0x29,0x95,0x19,0x92,0xaa,0x49,0x7d,0x3b,0xfb,0x50,0xb7,0xf3,0x5e,0x3e,0x6b, + 0x3a,0x14,0x2b,0xb4,0xfe,0xe6,0x93,0x23,0xd6,0x1f,0xd2,0x0c,0x1d,0x9d,0x6c,0x66, + 0x1c,0x89,0xbf,0xf6,0xff,0x6f,0x84,0x6e,0x2e,0xea,0x21,0xf7,0x7f,0x33,0xf1,0xe4, + 0x3d,0x0f,0x05,0x08,0x4e,0xa2,0xa0,0x2f,0xdc,0x00,0x5f,0x15,0x7e,0x02,0x4b,0x26 }; constexpr inline uint8_t pearson_hash_8(const char *s, uint8_t inv) { - return (*s) ? pearson_hash_8(s + 1, pearson_hash_table[inv ^ *s]) : inv; + return (*s) ? pearson_hash_8(s + 1, pearson_hash_table[inv ^ *s]) : inv; } constexpr inline uint32_t djb_hash_32(const char *s, int off = 0) { - return !s[off] ? 5381 : (djb_hash_32(s, off+1)*33) ^ s[off]; + return !s[off] ? 5381 : (djb_hash_32(s, off+1)*33) ^ s[off]; } } // namespace kutil constexpr inline uint8_t operator "" _h (const char *s, size_t len) { - return kutil::pearson_hash_8(s, static_cast(len & 0xff)); + return kutil::pearson_hash_8(s, static_cast(len & 0xff)); } diff --git a/src/libraries/kutil/include/kutil/coord.h b/src/libraries/kutil/include/kutil/coord.h index 32425bf..f7f36e5 100644 --- a/src/libraries/kutil/include/kutil/coord.h +++ b/src/libraries/kutil/include/kutil/coord.h @@ -5,10 +5,10 @@ namespace kutil { template struct coord { - T x, y; - coord() : x(T{}), y(T{}) {} - coord(T x, T y) : x(x), y(y) {} - T size() const { return x * y; } + T x, y; + coord() : x(T{}), y(T{}) {} + coord(T x, T y) : x(x), y(y) {} + T size() const { return x * y; } }; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/guid.h b/src/libraries/kutil/include/kutil/guid.h index c394913..68003c4 100644 --- a/src/libraries/kutil/include/kutil/guid.h +++ b/src/libraries/kutil/include/kutil/guid.h @@ -10,7 +10,7 @@ namespace kutil { /// A GUID struct guid { - uint64_t a, b; + uint64_t a, b; }; /// Make a GUID by writing it naturally-ordered in code: @@ -19,17 +19,17 @@ struct guid /// \returns The guid object inline constexpr guid make_guid(uint32_t a, uint16_t b, uint16_t c, uint16_t d, uint64_t e) { - const uint64_t h = - static_cast(c) << 48 | - static_cast(b) << 32 | - a; + const uint64_t h = + static_cast(c) << 48 | + static_cast(b) << 32 | + a; - const uint64_t l = - static_cast(byteswap(e & 0xffffffff)) << 32 | - (byteswap(e >> 32) & 0xffff0000) | - ((d << 8) & 0xff00) | ((d >> 8) & 0xff); + const uint64_t l = + static_cast(byteswap(e & 0xffffffff)) << 32 | + (byteswap(e >> 32) & 0xffff0000) | + ((d << 8) & 0xff00) | ((d >> 8) & 0xff); - return {h, l}; + return {h, l}; } } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/hash.h b/src/libraries/kutil/include/kutil/hash.h index f3f195e..308e583 100644 --- a/src/libraries/kutil/include/kutil/hash.h +++ b/src/libraries/kutil/include/kutil/hash.h @@ -12,29 +12,29 @@ constexpr uint64_t fnv1a_64_init = 0xcbf29ce484222325ull; /// Return the FNV-1a hash of the given 0-terminated string. inline uint64_t hash_string(char const *s, uint64_t init = 0) { - if (!init) init = fnv1a_64_init; - while(s && *s) { - init ^= static_cast(*s++); - init *= fnv_64_prime; - } - return init; + if (!init) init = fnv1a_64_init; + while(s && *s) { + init ^= static_cast(*s++); + init *= fnv_64_prime; + } + return init; } /// Return the FNV-1a hash of the given buffer. inline uint64_t hash_buffer(const void *v, size_t len, uint64_t init = 0) { - uint8_t const *p = reinterpret_cast(v); - uint8_t const *end = p + len; - if (!init) init = fnv1a_64_init; - while(p < end) { - init ^= static_cast(*p++); - init *= fnv_64_prime; - } - return init; + uint8_t const *p = reinterpret_cast(v); + uint8_t const *end = p + len; + if (!init) init = fnv1a_64_init; + while(p < end) { + init ^= static_cast(*p++); + init *= fnv_64_prime; + } + return init; } template inline uint64_t hash(const T &v) { - return hash_buffer(reinterpret_cast(&v), sizeof(T)); + return hash_buffer(reinterpret_cast(&v), sizeof(T)); } template <> inline uint64_t hash(const uint64_t &i) { return i; } diff --git a/src/libraries/kutil/include/kutil/heap_allocator.h b/src/libraries/kutil/include/kutil/heap_allocator.h index 0424af4..76ecacf 100644 --- a/src/libraries/kutil/include/kutil/heap_allocator.h +++ b/src/libraries/kutil/include/kutil/heap_allocator.h @@ -12,55 +12,55 @@ namespace kutil { class heap_allocator { public: - /// Default constructor creates a valid but empty heap. - heap_allocator(); + /// Default constructor creates a valid but empty heap. + heap_allocator(); - /// Constructor. The given memory area must already have been reserved. - /// \arg start Starting address of the heap - /// \arg size Size of the heap in bytes - heap_allocator(uintptr_t start, size_t size); + /// Constructor. The given memory area must already have been reserved. + /// \arg start Starting address of the heap + /// \arg size Size of the heap in bytes + heap_allocator(uintptr_t start, size_t size); - /// Allocate memory from the area managed. - /// \arg length The amount of memory to allocate, in bytes - /// \returns A pointer to the allocated memory, or nullptr if - /// allocation failed. - void * allocate(size_t length); + /// Allocate memory from the area managed. + /// \arg length The amount of memory to allocate, in bytes + /// \returns A pointer to the allocated memory, or nullptr if + /// allocation failed. + void * allocate(size_t length); - /// Free a previous allocation. - /// \arg p A pointer previously retuned by allocate() - void free(void *p); + /// Free a previous allocation. + /// \arg p A pointer previously retuned by allocate() + void free(void *p); - /// Minimum block size is (2^min_order). Must be at least 6. - static const unsigned min_order = 6; + /// Minimum block size is (2^min_order). Must be at least 6. + static const unsigned min_order = 6; - /// Maximum block size is (2^max_order). Must be less than 64. - static const unsigned max_order = 22; + /// Maximum block size is (2^max_order). Must be less than 64. + static const unsigned max_order = 22; protected: - class mem_header; + class mem_header; - /// Ensure there is a block of a given order, recursively splitting - /// \arg order Order (2^N) of the block we want - void ensure_block(unsigned order); + /// Ensure there is a block of a given order, recursively splitting + /// \arg order Order (2^N) of the block we want + void ensure_block(unsigned order); - /// Helper accessor for the list of blocks of a given order - /// \arg order Order (2^N) of the block we want - /// \returns A mutable reference to the head of the list - mem_header *& get_free(unsigned order) { return m_free[order - min_order]; } + /// Helper accessor for the list of blocks of a given order + /// \arg order Order (2^N) of the block we want + /// \returns A mutable reference to the head of the list + mem_header *& get_free(unsigned order) { return m_free[order - min_order]; } - /// Helper to get a block of the given order, growing if necessary - /// \arg order Order (2^N) of the block we want - /// \returns A detached block of the given order - mem_header * pop_free(unsigned order); + /// Helper to get a block of the given order, growing if necessary + /// \arg order Order (2^N) of the block we want + /// \returns A detached block of the given order + mem_header * pop_free(unsigned order); - uintptr_t m_start, m_end; - size_t m_blocks; - mem_header *m_free[max_order - min_order + 1]; - size_t m_allocated_size; + uintptr_t m_start, m_end; + size_t m_blocks; + mem_header *m_free[max_order - min_order + 1]; + size_t m_allocated_size; - spinlock m_lock; + spinlock m_lock; - heap_allocator(const heap_allocator &) = delete; + heap_allocator(const heap_allocator &) = delete; }; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/linked_list.h b/src/libraries/kutil/include/kutil/linked_list.h index b18cec2..42425a1 100644 --- a/src/libraries/kutil/include/kutil/linked_list.h +++ b/src/libraries/kutil/include/kutil/linked_list.h @@ -11,77 +11,77 @@ template class linked_list; /// A list node in a `linked_list` or `sortable_linked_list`. template class list_node : - public T + public T { public: - using item_type = T; - using node_type = list_node; + using item_type = T; + using node_type = list_node; - /// Dereference operator. Helper to cast this node to the contained type. - /// \returns A pointer to the node, cast to T*. - inline item_type & operator*() { return *this; } + /// Dereference operator. Helper to cast this node to the contained type. + /// \returns A pointer to the node, cast to T*. + inline item_type & operator*() { return *this; } - /// Dereference operator. Helper to cast this node to the contained type. - /// \returns A pointer to the node, cast to T*. - inline const item_type & operator*() const { return *this; } + /// Dereference operator. Helper to cast this node to the contained type. + /// \returns A pointer to the node, cast to T*. + inline const item_type & operator*() const { return *this; } - /// Cast operator. Helper to cast this node to the contained type. - /// \returns A reference to the node, cast to T&. - inline operator item_type& () { return *this; } + /// Cast operator. Helper to cast this node to the contained type. + /// \returns A reference to the node, cast to T&. + inline operator item_type& () { return *this; } - /// Cast operator. Helper to cast this node to the contained type. - /// \returns A reference to the node, cast to const T&. - inline operator const item_type& () { return *this; } + /// Cast operator. Helper to cast this node to the contained type. + /// \returns A reference to the node, cast to const T&. + inline operator const item_type& () { return *this; } - /// Accessor for the next pointer. - /// \returns The next node in the list - inline node_type * next() { return m_next; } + /// Accessor for the next pointer. + /// \returns The next node in the list + inline node_type * next() { return m_next; } - /// Accessor for the next pointer. - /// \returns The next node in the list - inline const node_type * next() const { return m_next; } + /// Accessor for the next pointer. + /// \returns The next node in the list + inline const node_type * next() const { return m_next; } - /// Accessor for the prev pointer. - /// \returns The prev node in the list - inline node_type * prev() { return m_prev; } + /// Accessor for the prev pointer. + /// \returns The prev node in the list + inline node_type * prev() { return m_prev; } - /// Accessor for the prev pointer. - /// \returns The prev node in the list - inline const node_type * prev() const { return m_prev; } + /// Accessor for the prev pointer. + /// \returns The prev node in the list + inline const node_type * prev() const { return m_prev; } private: - friend class linked_list; + friend class linked_list; - /// Insert an item after this one in the list. - /// \arg item The item to insert - void insert_after(node_type *item) - { - if (m_next) m_next->m_prev = item; - item->m_next = m_next; - item->m_prev = this; - m_next = item; - } + /// Insert an item after this one in the list. + /// \arg item The item to insert + void insert_after(node_type *item) + { + if (m_next) m_next->m_prev = item; + item->m_next = m_next; + item->m_prev = this; + m_next = item; + } - /// Insert an item before this one in the list. - /// \arg item The item to insert - void insert_before(node_type *item) - { - if (m_prev) m_prev->m_next = item; - item->m_prev = m_prev; - item->m_next = this; - m_prev = item; - } + /// Insert an item before this one in the list. + /// \arg item The item to insert + void insert_before(node_type *item) + { + if (m_prev) m_prev->m_next = item; + item->m_prev = m_prev; + item->m_next = this; + m_prev = item; + } - /// Remove this item from its list. - void remove() - { - if (m_next) m_next->m_prev = m_prev; - if (m_prev) m_prev->m_next = m_next; - m_next = m_prev = nullptr; - } + /// Remove this item from its list. + void remove() + { + if (m_next) m_next->m_prev = m_prev; + if (m_prev) m_prev->m_next = m_next; + m_next = m_prev = nullptr; + } - node_type *m_next; - node_type *m_prev; + node_type *m_next; + node_type *m_prev; }; @@ -90,18 +90,18 @@ template class list_iterator { public: - using item_type = list_node; + using item_type = list_node; - list_iterator(item_type *item) : m_item(item) {} + list_iterator(item_type *item) : m_item(item) {} - inline item_type * operator*() { return m_item; } - inline const item_type * operator*() const { return m_item; } - inline list_iterator & operator++() { m_item = m_item ? m_item->next() : nullptr; return *this; } - inline list_iterator operator++(int) { return list_iterator(m_item ? m_item->next() : nullptr); } - inline bool operator!=(const list_iterator &other) { return m_item != other.m_item; } + inline item_type * operator*() { return m_item; } + inline const item_type * operator*() const { return m_item; } + inline list_iterator & operator++() { m_item = m_item ? m_item->next() : nullptr; return *this; } + inline list_iterator operator++(int) { return list_iterator(m_item ? m_item->next() : nullptr); } + inline bool operator!=(const list_iterator &other) { return m_item != other.m_item; } private: - item_type *m_item; + item_type *m_item; }; @@ -110,239 +110,239 @@ template class linked_list { public: - using item_type = list_node; - using iterator = list_iterator; + using item_type = list_node; + using iterator = list_iterator; - /// Constructor. Creates an empty list. - linked_list() : - m_head(nullptr), - m_tail(nullptr), - m_count(0) - {} + /// Constructor. Creates an empty list. + linked_list() : + m_head(nullptr), + m_tail(nullptr), + m_count(0) + {} - /// Move constructor. Takes ownership of list elements. - linked_list(linked_list &&other) : - m_head(other.m_head), - m_tail(other.m_tail), - m_count(other.m_count) - { - other.m_head = other.m_tail = nullptr; - other.m_count = 0; - } + /// Move constructor. Takes ownership of list elements. + linked_list(linked_list &&other) : + m_head(other.m_head), + m_tail(other.m_tail), + m_count(other.m_count) + { + other.m_head = other.m_tail = nullptr; + other.m_count = 0; + } - /// Assignment operator. Takes ownership of list elements. - /// Destructive towards current data! - linked_list & operator=(linked_list &&other) - { - m_head = other.m_head; - m_tail = other.m_tail; - m_count = other.m_count; - other.m_head = other.m_tail = nullptr; - other.m_count = 0; - return *this; - } + /// Assignment operator. Takes ownership of list elements. + /// Destructive towards current data! + linked_list & operator=(linked_list &&other) + { + m_head = other.m_head; + m_tail = other.m_tail; + m_count = other.m_count; + other.m_head = other.m_tail = nullptr; + other.m_count = 0; + return *this; + } - /// Check if the list is empty. - /// \returns true if the list is empty - bool empty() const { return m_head == nullptr; } + /// Check if the list is empty. + /// \returns true if the list is empty + bool empty() const { return m_head == nullptr; } - /// Get the cached length of the list. - /// \returns The number of entries in the list. - size_t length() const { return m_count; } + /// Get the cached length of the list. + /// \returns The number of entries in the list. + size_t length() const { return m_count; } - /// Count the items in the list. - /// \returns The number of entries in the list. - size_t count_length() - { - size_t len = 0; - for (item_type *cur = m_head; cur; cur = cur->m_next) ++len; - m_count = len; - return len; - } + /// Count the items in the list. + /// \returns The number of entries in the list. + size_t count_length() + { + size_t len = 0; + for (item_type *cur = m_head; cur; cur = cur->m_next) ++len; + m_count = len; + return len; + } - /// Get the item at the front of the list, without removing it - /// \returns The first item in the list - inline item_type * front() { return m_head; } + /// Get the item at the front of the list, without removing it + /// \returns The first item in the list + inline item_type * front() { return m_head; } - /// Get the item at the back of the list, without removing it - /// \returns The last item in the list - inline item_type * back() { return m_tail; } + /// Get the item at the back of the list, without removing it + /// \returns The last item in the list + inline item_type * back() { return m_tail; } - /// Prepend an item to the front of this list. - /// \arg item The node to insert. - void push_front(item_type *item) - { - if (!item) - return; + /// Prepend an item to the front of this list. + /// \arg item The node to insert. + void push_front(item_type *item) + { + if (!item) + return; - if (!m_head) { - m_head = m_tail = item; - item->m_next = item->m_prev = nullptr; - } else { - m_head->m_prev = item; - item->m_next = m_head; - item->m_prev = nullptr; - m_head = item; - } + if (!m_head) { + m_head = m_tail = item; + item->m_next = item->m_prev = nullptr; + } else { + m_head->m_prev = item; + item->m_next = m_head; + item->m_prev = nullptr; + m_head = item; + } - m_count += 1; - } + m_count += 1; + } - /// Append an item to the end of this list. - /// \arg item The node to append. - void push_back(item_type *item) - { - if (!item) - return; + /// Append an item to the end of this list. + /// \arg item The node to append. + void push_back(item_type *item) + { + if (!item) + return; - if (!m_tail) { - m_head = m_tail = item; - item->m_next = item->m_prev = nullptr; - } else { - m_tail->m_next = item; - item->m_prev = m_tail; - item->m_next = nullptr; - m_tail = item; - } + if (!m_tail) { + m_head = m_tail = item; + item->m_next = item->m_prev = nullptr; + } else { + m_tail->m_next = item; + item->m_prev = m_tail; + item->m_next = nullptr; + m_tail = item; + } - m_count += 1; - } + m_count += 1; + } - /// Remove an item from the front of this list. - /// \returns The node that was removed - item_type * pop_front() - { - item_type *item = m_head; - remove(item); - return item; - } + /// Remove an item from the front of this list. + /// \returns The node that was removed + item_type * pop_front() + { + item_type *item = m_head; + remove(item); + return item; + } - /// Remove an item from the end of this list. - /// \returns The node that was removed - item_type * pop_back() - { - item_type *item = m_tail; - remove(item); - return item; - } + /// Remove an item from the end of this list. + /// \returns The node that was removed + item_type * pop_back() + { + item_type *item = m_tail; + remove(item); + return item; + } - /// Append the contents of another list to the end of this list. The other - /// list is emptied, and this list takes ownership of its items. - /// \arg list The other list. - void append(linked_list &list) - { - if (!list.m_head) return; + /// Append the contents of another list to the end of this list. The other + /// list is emptied, and this list takes ownership of its items. + /// \arg list The other list. + void append(linked_list &list) + { + if (!list.m_head) return; - if (!m_tail) { - m_head = list.m_head; - m_tail = list.m_tail; - } else { - m_tail->m_next = list.m_head; - m_tail = list.m_tail; - } + if (!m_tail) { + m_head = list.m_head; + m_tail = list.m_tail; + } else { + m_tail->m_next = list.m_head; + m_tail = list.m_tail; + } - m_count += list.m_count; - list.m_count = 0; - list.m_head = list.m_tail = nullptr; - } + m_count += list.m_count; + list.m_count = 0; + list.m_head = list.m_tail = nullptr; + } - /// Append the contents of another list to the end of this list. The other - /// list is emptied, and this list takes ownership of its items. - /// \arg list The other list. - void append(linked_list &&list) - { - if (!list.m_head) return; + /// Append the contents of another list to the end of this list. The other + /// list is emptied, and this list takes ownership of its items. + /// \arg list The other list. + void append(linked_list &&list) + { + if (!list.m_head) return; - if (!m_tail) { - m_head = list.m_head; - m_tail = list.m_tail; - } else { - m_tail->m_next = list.m_head; - m_tail = list.m_tail; - } + if (!m_tail) { + m_head = list.m_head; + m_tail = list.m_tail; + } else { + m_tail->m_next = list.m_head; + m_tail = list.m_tail; + } - m_count += list.m_count; - list.m_count = 0; - list.m_head = list.m_tail = nullptr; - } + m_count += list.m_count; + list.m_count = 0; + list.m_head = list.m_tail = nullptr; + } - /// Remove an item from the list. - /// \arg item The item to remove - void remove(item_type *item) - { - if (!item) return; - if (item == m_head) - m_head = item->m_next; - if (item == m_tail) - m_tail = item->m_prev; - item->remove(); - m_count -= 1; - } + /// Remove an item from the list. + /// \arg item The item to remove + void remove(item_type *item) + { + if (!item) return; + if (item == m_head) + m_head = item->m_next; + if (item == m_tail) + m_tail = item->m_prev; + item->remove(); + m_count -= 1; + } - /// Inserts an item into the list before another given item. - /// \arg existing The existing item to insert before - /// \arg item The new item to insert - void insert_before(item_type *existing, item_type *item) - { - if (!item) return; + /// Inserts an item into the list before another given item. + /// \arg existing The existing item to insert before + /// \arg item The new item to insert + void insert_before(item_type *existing, item_type *item) + { + if (!item) return; - if (!existing) { - push_back(item); - } else if (existing == m_head) { - push_front(item); - } else { - existing->insert_before(item); - m_count += 1; - } - } + if (!existing) { + push_back(item); + } else if (existing == m_head) { + push_front(item); + } else { + existing->insert_before(item); + m_count += 1; + } + } - /// Inserts an item into the list after another given item. - /// \arg existing The existing item to insert after - /// \arg item The new item to insert - void insert_after(item_type *existing, item_type *item) - { - if (!item) return; + /// Inserts an item into the list after another given item. + /// \arg existing The existing item to insert after + /// \arg item The new item to insert + void insert_after(item_type *existing, item_type *item) + { + if (!item) return; - if (!existing) { - push_front(item); - } else if (existing == m_tail) { - push_back(item); - } else { - existing->insert_after(item); - m_count += 1; - } - } + if (!existing) { + push_front(item); + } else if (existing == m_tail) { + push_back(item); + } else { + existing->insert_after(item); + m_count += 1; + } + } - /// Insert an item into the list in a sorted position. Depends on T - /// having a method `int compare(const T *other)`. - /// \arg item The item to insert - void sorted_insert(item_type *item) - { - if (!item) return; + /// Insert an item into the list in a sorted position. Depends on T + /// having a method `int compare(const T *other)`. + /// \arg item The item to insert + void sorted_insert(item_type *item) + { + if (!item) return; - item_type *cur = m_head; - while (cur && item->compare(*cur) > 0) - cur = cur->m_next; + item_type *cur = m_head; + while (cur && item->compare(*cur) > 0) + cur = cur->m_next; - insert_before(cur, item); - } + insert_before(cur, item); + } - /// Range-based for iterator generator. - /// \returns An iterator to the beginning of the list - inline iterator begin() { return iterator(m_head); } + /// Range-based for iterator generator. + /// \returns An iterator to the beginning of the list + inline iterator begin() { return iterator(m_head); } - /// Range-based for iterator generator. - /// \returns A const iterator to the beginning of the list - inline const iterator begin() const { return iterator(m_head); } + /// Range-based for iterator generator. + /// \returns A const iterator to the beginning of the list + inline const iterator begin() const { return iterator(m_head); } - /// Range-based for end-iterator generator. - /// \returns An iterator to the end of the list - inline const iterator end() const { return iterator(nullptr); } + /// Range-based for end-iterator generator. + /// \returns An iterator to the end of the list + inline const iterator end() const { return iterator(nullptr); } private: - item_type *m_head; - item_type *m_tail; - size_t m_count; + item_type *m_head; + item_type *m_tail; + size_t m_count; }; diff --git a/src/libraries/kutil/include/kutil/logger.h b/src/libraries/kutil/include/kutil/logger.h index f260fe2..3e94c2f 100644 --- a/src/libraries/kutil/include/kutil/logger.h +++ b/src/libraries/kutil/include/kutil/logger.h @@ -13,109 +13,109 @@ namespace log { using area_t = uint8_t; enum class level : uint8_t { - none, debug, info, warn, error, fatal, max + none, debug, info, warn, error, fatal, max }; class logger { public: - /// Callback type for immediate-mode logging - typedef void (*immediate_cb)(area_t, level, const char *); + /// Callback type for immediate-mode logging + typedef void (*immediate_cb)(area_t, level, const char *); - /// Callback type for log flushing - typedef void (*flush_cb)(); + /// Callback type for log flushing + typedef void (*flush_cb)(); - /// Default constructor. Creates a logger without a backing store. - /// \arg output Immediate-mode logging output function - logger(immediate_cb output = nullptr); + /// Default constructor. Creates a logger without a backing store. + /// \arg output Immediate-mode logging output function + logger(immediate_cb output = nullptr); - /// Constructor. Logs are written to the given buffer. - /// \arg buffer Buffer to which logs are written - /// \arg size Size of `buffer`, in bytes - /// \arg output Immediate-mode logging output function - logger(uint8_t *buffer, size_t size, immediate_cb output = nullptr); + /// Constructor. Logs are written to the given buffer. + /// \arg buffer Buffer to which logs are written + /// \arg size Size of `buffer`, in bytes + /// \arg output Immediate-mode logging output function + logger(uint8_t *buffer, size_t size, immediate_cb output = nullptr); - /// Register a log area for future use. - /// \arg area The key for the new area - /// \arg name The area name - /// \arg verbosity What level of logs to print for this area - void register_area(area_t area, const char *name, level verbosity); + /// Register a log area for future use. + /// \arg area The key for the new area + /// \arg name The area name + /// \arg verbosity What level of logs to print for this area + void register_area(area_t area, const char *name, level verbosity); - /// Register an immediate-mode log callback - inline void set_immediate(immediate_cb cb) { m_immediate = cb; } + /// Register an immediate-mode log callback + inline void set_immediate(immediate_cb cb) { m_immediate = cb; } - /// Register a flush callback - inline void set_flush(flush_cb cb) { m_flush = cb; } + /// Register a flush callback + inline void set_flush(flush_cb cb) { m_flush = cb; } - /// Get the default logger. - inline logger & get() { return *s_log; } + /// Get the default logger. + inline logger & get() { return *s_log; } - /// Get the registered name for a given area - inline const char * area_name(area_t area) const { return m_names[area]; } + /// Get the registered name for a given area + inline const char * area_name(area_t area) const { return m_names[area]; } - /// Get the name of a level - inline const char * level_name(level l) const { return s_level_names[static_cast(l)]; } + /// Get the name of a level + inline const char * level_name(level l) const { return s_level_names[static_cast(l)]; } - /// Write to the log - /// \arg severity The severity of the message - /// \arg area The log area to write to - /// \arg fmt A printf-like format string - inline void log(level severity, area_t area, const char *fmt, ...) - { - level limit = get_level(area); - if (limit == level::none || severity < limit) - return; + /// Write to the log + /// \arg severity The severity of the message + /// \arg area The log area to write to + /// \arg fmt A printf-like format string + inline void log(level severity, area_t area, const char *fmt, ...) + { + level limit = get_level(area); + if (limit == level::none || severity < limit) + return; - va_list args; - va_start(args, fmt); - output(severity, area, fmt, args); - va_end(args); - } + va_list args; + va_start(args, fmt); + output(severity, area, fmt, args); + va_end(args); + } - struct entry - { - uint8_t bytes; - area_t area; - level severity; - uint8_t sequence; - char message[0]; - }; + struct entry + { + uint8_t bytes; + area_t area; + level severity; + uint8_t sequence; + char message[0]; + }; - /// Get the next log entry from the buffer - /// \arg buffer The buffer to copy the log message into - /// \arg size Size of the passed-in buffer, in bytes - /// \returns The size of the log entry (if larger than the - /// buffer, then no data was copied) - size_t get_entry(void *buffer, size_t size); + /// Get the next log entry from the buffer + /// \arg buffer The buffer to copy the log message into + /// \arg size Size of the passed-in buffer, in bytes + /// \returns The size of the log entry (if larger than the + /// buffer, then no data was copied) + size_t get_entry(void *buffer, size_t size); - /// Get whether there is currently data in the log buffer - inline bool has_log() const { return m_buffer.size(); } + /// Get whether there is currently data in the log buffer + inline bool has_log() const { return m_buffer.size(); } private: - friend void debug(area_t area, const char *fmt, ...); - friend void info (area_t area, const char *fmt, ...); - friend void warn (area_t area, const char *fmt, ...); - friend void error(area_t area, const char *fmt, ...); - friend void fatal(area_t area, const char *fmt, ...); + friend void debug(area_t area, const char *fmt, ...); + friend void info (area_t area, const char *fmt, ...); + friend void warn (area_t area, const char *fmt, ...); + friend void error(area_t area, const char *fmt, ...); + friend void fatal(area_t area, const char *fmt, ...); - void output(level severity, area_t area, const char *fmt, va_list args); + void output(level severity, area_t area, const char *fmt, va_list args); - void set_level(area_t area, level l); - level get_level(area_t area); + void set_level(area_t area, level l); + level get_level(area_t area); - static const unsigned num_areas = 1 << (sizeof(area_t) * 8); - uint8_t m_levels[num_areas / 2]; - const char *m_names[num_areas]; - immediate_cb m_immediate; - flush_cb m_flush; + static const unsigned num_areas = 1 << (sizeof(area_t) * 8); + uint8_t m_levels[num_areas / 2]; + const char *m_names[num_areas]; + immediate_cb m_immediate; + flush_cb m_flush; - uint8_t m_sequence; + uint8_t m_sequence; - kutil::bip_buffer m_buffer; - kutil::spinlock m_lock; + kutil::bip_buffer m_buffer; + kutil::spinlock m_lock; - static logger *s_log; - static const char *s_level_names[static_cast(level::max)]; + static logger *s_log; + static const char *s_level_names[static_cast(level::max)]; }; void debug(area_t area, const char *fmt, ...); diff --git a/src/libraries/kutil/include/kutil/map.h b/src/libraries/kutil/include/kutil/map.h index 4ea1ddf..e46321c 100644 --- a/src/libraries/kutil/include/kutil/map.h +++ b/src/libraries/kutil/include/kutil/map.h @@ -24,25 +24,25 @@ inline bool equal(const T &a, const T &b) { return a == b; } template <> inline bool equal(const char * const &a, const char * const &b) { - if (!a || !b) return a == b; - const char *a1 = a, *b1 = b; - while (*a1 && *b1) if (*a1++ != *b1++) return false; - return *a1 == *b1; // Make sure they're both zero + if (!a || !b) return a == b; + const char *a1 = a, *b1 = b; + while (*a1 && *b1) if (*a1++ != *b1++) return false; + return *a1 == *b1; // Make sure they're both zero } template struct hash_node { - uint64_t h {0}; - K key; - V val; + uint64_t h {0}; + K key; + V val; - hash_node(hash_node &&o) : h(o.h), key(std::move(o.key)), val(std::move(o.val)) {} - hash_node(uint64_t h, K &&k, V &&v) : h(h), key(std::move(k)), val(std::move(v)) {} - ~hash_node() { h = 0; } + hash_node(hash_node &&o) : h(o.h), key(std::move(o.key)), val(std::move(o.val)) {} + hash_node(uint64_t h, K &&k, V &&v) : h(h), key(std::move(k)), val(std::move(v)) {} + ~hash_node() { h = 0; } - inline uint64_t & hash() { return h; } - inline uint64_t hash() const { return h; } + inline uint64_t & hash() { return h; } + inline uint64_t hash() const { return h; } }; /// Base class for hash maps @@ -50,242 +50,242 @@ template class base_map { protected: - using node = hash_node; + using node = hash_node; public: - static constexpr size_t min_capacity = 8; - static constexpr size_t max_load = 90; + static constexpr size_t min_capacity = 8; + static constexpr size_t max_load = 90; - class iterator - { - public: - inline node & operator*() { return *m_node; } - inline node * operator->() { return m_node; } - inline const node & operator*() const { return *m_node; } - inline iterator & operator++() { incr(); return *this; } - inline iterator operator++(int) { node *old = m_node; incr(); return iterator(old); } - inline bool operator!=(const iterator &o) { return m_node != o.m_node; } - private: - friend class base_map; - iterator(node *n) : m_node(n), m_end(n) {} - iterator(node *n, node *end) : m_node(n), m_end(end) {} - void incr() { while (m_node < m_end) { ++m_node; if (m_node->hash()) break; } } - node *m_node; - node *m_end; - }; + class iterator + { + public: + inline node & operator*() { return *m_node; } + inline node * operator->() { return m_node; } + inline const node & operator*() const { return *m_node; } + inline iterator & operator++() { incr(); return *this; } + inline iterator operator++(int) { node *old = m_node; incr(); return iterator(old); } + inline bool operator!=(const iterator &o) { return m_node != o.m_node; } + private: + friend class base_map; + iterator(node *n) : m_node(n), m_end(n) {} + iterator(node *n, node *end) : m_node(n), m_end(end) {} + void incr() { while (m_node < m_end) { ++m_node; if (m_node->hash()) break; } } + node *m_node; + node *m_end; + }; - /// Default constructor. Creates an empty map with the given capacity. - base_map(size_t capacity = 0) : - m_count(0), - m_capacity(0), - m_nodes(nullptr) - { - if (capacity) - set_capacity(1 << log2(capacity)); - } + /// Default constructor. Creates an empty map with the given capacity. + base_map(size_t capacity = 0) : + m_count(0), + m_capacity(0), + m_nodes(nullptr) + { + if (capacity) + set_capacity(1 << log2(capacity)); + } - virtual ~base_map() { - for (size_t i = 0; i < m_capacity; ++i) - m_nodes[i].~node(); - kfree(m_nodes); - } + virtual ~base_map() { + for (size_t i = 0; i < m_capacity; ++i) + m_nodes[i].~node(); + kfree(m_nodes); + } - iterator begin() { - if (!m_count) return iterator {0}; - iterator it {m_nodes - 1, m_nodes + m_capacity}; - return ++it; - } + iterator begin() { + if (!m_count) return iterator {0}; + iterator it {m_nodes - 1, m_nodes + m_capacity}; + return ++it; + } - const iterator begin() const { - if (!m_count) return iterator {0}; - iterator it {m_nodes - 1, m_nodes + m_capacity}; - return ++it; - } + const iterator begin() const { + if (!m_count) return iterator {0}; + iterator it {m_nodes - 1, m_nodes + m_capacity}; + return ++it; + } - const iterator end() const { - if (!m_count) return iterator {0}; - return iterator(m_nodes + m_capacity); - } + const iterator end() const { + if (!m_count) return iterator {0}; + return iterator(m_nodes + m_capacity); + } - void insert(K k, V v) { - if (++m_count > threshold()) grow(); - insert_node(hash(k), std::move(k), std::move(v)); - } + void insert(K k, V v) { + if (++m_count > threshold()) grow(); + insert_node(hash(k), std::move(k), std::move(v)); + } - bool erase(const K &k) - { - node *n = lookup(k); - if (!n) return false; + bool erase(const K &k) + { + node *n = lookup(k); + if (!n) return false; - n->~node(); - --m_count; + n->~node(); + --m_count; - size_t i = n - m_nodes; - while (true) { - size_t next = mod(i+1); - node &m = m_nodes[next]; - if (!m.hash() || mod(m.hash()) == next) break; - construct(i, m.hash(), std::move(m.key), std::move(m.val)); - m.~node(); - i = mod(++i); - } + size_t i = n - m_nodes; + while (true) { + size_t next = mod(i+1); + node &m = m_nodes[next]; + if (!m.hash() || mod(m.hash()) == next) break; + construct(i, m.hash(), std::move(m.key), std::move(m.val)); + m.~node(); + i = mod(++i); + } - return true; - } + return true; + } - inline size_t count() const { return m_count; } - inline size_t capacity() const { return m_capacity; } - inline size_t threshold() const { return (m_capacity * max_load) / 100; } + inline size_t count() const { return m_count; } + inline size_t capacity() const { return m_capacity; } + inline size_t threshold() const { return (m_capacity * max_load) / 100; } protected: - inline size_t mod(uint64_t i) const { return i & (m_capacity - 1); } - inline size_t offset(uint64_t h, size_t i) const { - return mod(i + m_capacity - mod(h)); - } + inline size_t mod(uint64_t i) const { return i & (m_capacity - 1); } + inline size_t offset(uint64_t h, size_t i) const { + return mod(i + m_capacity - mod(h)); + } - void set_capacity(size_t capacity) { - kassert((capacity & (capacity - 1)) == 0, - "Map capacity must be a power of two"); + void set_capacity(size_t capacity) { + kassert((capacity & (capacity - 1)) == 0, + "Map capacity must be a power of two"); - m_capacity = capacity; - const size_t size = m_capacity * sizeof(node); - m_nodes = reinterpret_cast(kalloc(size)); - kutil::memset(m_nodes, 0, size); - } + m_capacity = capacity; + const size_t size = m_capacity * sizeof(node); + m_nodes = reinterpret_cast(kalloc(size)); + kutil::memset(m_nodes, 0, size); + } - void grow() { - node *old = m_nodes; - size_t count = m_capacity; + void grow() { + node *old = m_nodes; + size_t count = m_capacity; - size_t cap = m_capacity * 2; - if (cap < min_capacity) - cap = min_capacity; + size_t cap = m_capacity * 2; + if (cap < min_capacity) + cap = min_capacity; - set_capacity(cap); + set_capacity(cap); - for (size_t i = 0; i < count; ++i) { - node &n = old[i]; - insert_node(n.hash(), std::move(n.key), std::move(n.val)); - n.~node(); - } + for (size_t i = 0; i < count; ++i) { + node &n = old[i]; + insert_node(n.hash(), std::move(n.key), std::move(n.val)); + n.~node(); + } - kfree(old); - } + kfree(old); + } - inline node * construct(size_t i, uint64_t h, K &&k, V &&v) { - return new (&m_nodes[i]) node(h, std::move(k), std::move(v)); - } + inline node * construct(size_t i, uint64_t h, K &&k, V &&v) { + return new (&m_nodes[i]) node(h, std::move(k), std::move(v)); + } - node * insert_node(uint64_t h, K &&k, V &&v) { - size_t i = mod(h); - size_t dist = 0; + node * insert_node(uint64_t h, K &&k, V &&v) { + size_t i = mod(h); + size_t dist = 0; - while (true) { - if (!m_nodes[i].hash()) { - return construct(i, h, std::move(k), std::move(v)); - } + while (true) { + if (!m_nodes[i].hash()) { + return construct(i, h, std::move(k), std::move(v)); + } - node &elem = m_nodes[i]; - size_t elem_dist = offset(elem.hash(), i); - if (elem_dist < dist) { - std::swap(h, elem.hash()); - std::swap(k, elem.key); - std::swap(v, elem.val); - dist = elem_dist; - } + node &elem = m_nodes[i]; + size_t elem_dist = offset(elem.hash(), i); + if (elem_dist < dist) { + std::swap(h, elem.hash()); + std::swap(k, elem.key); + std::swap(v, elem.val); + dist = elem_dist; + } - i = mod(++i); - ++dist; - } - } + i = mod(++i); + ++dist; + } + } - node * lookup(const K &k) { - if (!m_count) - return nullptr; + node * lookup(const K &k) { + if (!m_count) + return nullptr; - uint64_t h = hash(k); - size_t i = mod(h); - size_t dist = 0; + uint64_t h = hash(k); + size_t i = mod(h); + size_t dist = 0; - while (true) { - node &n = m_nodes[i]; - if (!n.hash() || dist > offset(n.hash(), i)) - return nullptr; + while (true) { + node &n = m_nodes[i]; + if (!n.hash() || dist > offset(n.hash(), i)) + return nullptr; - else if (n.hash() == h && equal(n.key, k)) - return &n; + else if (n.hash() == h && equal(n.key, k)) + return &n; - i = mod(++i); - ++dist; - } - } + i = mod(++i); + ++dist; + } + } - const node * lookup(const K &k) const { - if (!m_count) - return nullptr; + const node * lookup(const K &k) const { + if (!m_count) + return nullptr; - uint64_t h = hash(k); - size_t i = mod(h); - size_t dist = 0; + uint64_t h = hash(k); + size_t i = mod(h); + size_t dist = 0; - while (true) { - const node &n = m_nodes[i]; - if (!n.hash() || dist > offset(n.hash(), i)) - return nullptr; + while (true) { + const node &n = m_nodes[i]; + if (!n.hash() || dist > offset(n.hash(), i)) + return nullptr; - else if (n.hash() == h && equal(n.key, k)) - return &n; + else if (n.hash() == h && equal(n.key, k)) + return &n; - i = mod(++i); - ++dist; - } - } + i = mod(++i); + ++dist; + } + } - size_t m_count; - size_t m_capacity; - node *m_nodes; + size_t m_count; + size_t m_capacity; + node *m_nodes; }; /// An open addressing hash map using robinhood hashing. template class map : - public base_map + public base_map { - using base = base_map; - using node = typename base::node; + using base = base_map; + using node = typename base::node; public: - map(size_t capacity = 0) : - base(capacity) {} + map(size_t capacity = 0) : + base(capacity) {} - V * find(const K &k) { - node *n = this->lookup(k); - return n ? &n->val : nullptr; - } + V * find(const K &k) { + node *n = this->lookup(k); + return n ? &n->val : nullptr; + } - const V * find(const K &k) const { - const node *n = this->lookup(k); - return n ? &n->val : nullptr; - } + const V * find(const K &k) const { + const node *n = this->lookup(k); + return n ? &n->val : nullptr; + } }; /// An open addressing hash map using robinhood hashing. Specialization /// for storing pointers: don't return a pointer to a pointer. template class map : - public base_map + public base_map { - using base = base_map; - using node = typename base::node; + using base = base_map; + using node = typename base::node; public: - map(size_t capacity = 0) : - base(capacity) {} + map(size_t capacity = 0) : + base(capacity) {} - V * find(const K &k) const { - const node *n = this->lookup(k); - return n ? n->val : nullptr; - } + V * find(const K &k) const { + const node *n = this->lookup(k); + return n ? n->val : nullptr; + } }; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/memory.h b/src/libraries/kutil/include/kutil/memory.h index cf767a5..c5d8905 100644 --- a/src/libraries/kutil/include/kutil/memory.h +++ b/src/libraries/kutil/include/kutil/memory.h @@ -40,7 +40,7 @@ void * memcpy(void *dest, const void *src, size_t n); template inline T read_from(const void *p) { - return *reinterpret_cast(p); + return *reinterpret_cast(p); } /// Get a pointer that's offset from another pointer @@ -50,7 +50,7 @@ inline T read_from(const void *p) template inline T * offset_pointer(T *p, ptrdiff_t n) { - return reinterpret_cast(reinterpret_cast(p) + n); + return reinterpret_cast(reinterpret_cast(p) + n); } /// Return a pointer with the given bits masked out @@ -60,7 +60,7 @@ inline T * offset_pointer(T *p, ptrdiff_t n) template inline T* mask_pointer(T *p, uintptr_t mask) { - return reinterpret_cast(reinterpret_cast(p) & ~mask); + return reinterpret_cast(reinterpret_cast(p) & ~mask); } /// Do a simple byte-wise checksum of an area of memory. diff --git a/src/libraries/kutil/include/kutil/misc.h b/src/libraries/kutil/include/kutil/misc.h index 01cbf83..e455e13 100644 --- a/src/libraries/kutil/include/kutil/misc.h +++ b/src/libraries/kutil/include/kutil/misc.h @@ -5,8 +5,8 @@ namespace kutil { constexpr uint32_t byteswap(uint32_t x) { - return ((x >> 24) & 0x000000ff) | ((x >> 8) & 0x0000ff00) - | ((x << 8) & 0x00ff0000) | ((x << 24) & 0xff000000); + return ((x >> 24) & 0x000000ff) | ((x >> 8) & 0x0000ff00) + | ((x << 8) & 0x00ff0000) | ((x << 24) & 0xff000000); } } diff --git a/src/libraries/kutil/include/kutil/no_construct.h b/src/libraries/kutil/include/kutil/no_construct.h index 0bcdd82..0c42595 100644 --- a/src/libraries/kutil/include/kutil/no_construct.h +++ b/src/libraries/kutil/include/kutil/no_construct.h @@ -8,9 +8,9 @@ namespace kutil { template union no_construct { - T value; - no_construct() {} - ~no_construct() {} + T value; + no_construct() {} + ~no_construct() {} }; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/slab_allocated.h b/src/libraries/kutil/include/kutil/slab_allocated.h index 89afec0..d4b7f80 100644 --- a/src/libraries/kutil/include/kutil/slab_allocated.h +++ b/src/libraries/kutil/include/kutil/slab_allocated.h @@ -12,36 +12,36 @@ template class slab_allocated { public: - void * operator new(size_t size) - { - kassert(size == sizeof(T), "Slab allocator got wrong size allocation"); - if (s_free.count() == 0) - allocate_chunk(); + void * operator new(size_t size) + { + kassert(size == sizeof(T), "Slab allocator got wrong size allocation"); + if (s_free.count() == 0) + allocate_chunk(); - T *item = s_free.pop(); - kutil::memset(item, 0, sizeof(T)); - return item; - } + T *item = s_free.pop(); + kutil::memset(item, 0, sizeof(T)); + return item; + } - void operator delete(void *p) { s_free.append(reinterpret_cast(p)); } + void operator delete(void *p) { s_free.append(reinterpret_cast(p)); } private: - static void allocate_chunk() - { - size_t size = N * ::memory::frame_size; - s_free.ensure_capacity(size / sizeof(T)); + static void allocate_chunk() + { + size_t size = N * ::memory::frame_size; + s_free.ensure_capacity(size / sizeof(T)); - void *memory = kalloc(size); - T *current = reinterpret_cast(memory); - T *end = offset_pointer(current, size); - while (current < end) - s_free.append(current++); - } + void *memory = kalloc(size); + T *current = reinterpret_cast(memory); + T *end = offset_pointer(current, size); + while (current < end) + s_free.append(current++); + } - static vector s_free; + static vector s_free; }; #define DEFINE_SLAB_ALLOCATOR(type, N) \ - template<> ::kutil::vector kutil::slab_allocated::s_free {}; + template<> ::kutil::vector kutil::slab_allocated::s_free {}; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/spinlock.h b/src/libraries/kutil/include/kutil/spinlock.h index 96bbfbe..f174805 100644 --- a/src/libraries/kutil/include/kutil/spinlock.h +++ b/src/libraries/kutil/include/kutil/spinlock.h @@ -9,38 +9,38 @@ namespace kutil { class spinlock { public: - spinlock(); - ~spinlock(); + spinlock(); + ~spinlock(); - /// A node in the wait queue. - struct waiter - { - bool blocked; - waiter *next; - }; + /// A node in the wait queue. + struct waiter + { + bool blocked; + waiter *next; + }; - void acquire(waiter *w); - void release(waiter *w); + void acquire(waiter *w); + void release(waiter *w); private: - waiter *m_lock; + waiter *m_lock; }; /// Scoped lock that owns a spinlock::waiter class scoped_lock { public: - inline scoped_lock(spinlock &lock) : m_lock(lock) { - m_lock.acquire(&m_waiter); - } + inline scoped_lock(spinlock &lock) : m_lock(lock) { + m_lock.acquire(&m_waiter); + } - inline ~scoped_lock() { - m_lock.release(&m_waiter); - } + inline ~scoped_lock() { + m_lock.release(&m_waiter); + } private: - spinlock &m_lock; - spinlock::waiter m_waiter; + spinlock &m_lock; + spinlock::waiter m_waiter; }; } // namespace kutil diff --git a/src/libraries/kutil/include/kutil/util.h b/src/libraries/kutil/include/kutil/util.h index d1e36b2..e1ecba8 100644 --- a/src/libraries/kutil/include/kutil/util.h +++ b/src/libraries/kutil/include/kutil/util.h @@ -8,9 +8,9 @@ namespace kutil { // Get the base-2 logarithm of i inline unsigned log2(uint64_t i) { - if (i < 2) return 0; - const unsigned clz = __builtin_clzll(i - 1); - return 64 - clz; + if (i < 2) return 0; + const unsigned clz = __builtin_clzll(i - 1); + return 64 - clz; } } diff --git a/src/libraries/kutil/include/kutil/vector.h b/src/libraries/kutil/include/kutil/vector.h index 18408cf..825f356 100644 --- a/src/libraries/kutil/include/kutil/vector.h +++ b/src/libraries/kutil/include/kutil/vector.h @@ -13,282 +13,282 @@ namespace kutil { template class vector { - using count_t = S; - static constexpr count_t min_capacity = 4; - static constexpr count_t cap_mask = static_cast(-1) >> 1; + using count_t = S; + static constexpr count_t min_capacity = 4; + static constexpr count_t cap_mask = static_cast(-1) >> 1; public: - /// Default constructor. Creates an empty vector with no capacity. - vector() : - m_size(0), - m_capacity(0), - m_elements(nullptr) - {} + /// Default constructor. Creates an empty vector with no capacity. + vector() : + m_size(0), + m_capacity(0), + m_elements(nullptr) + {} - /// Constructor. Creates an empty array with capacity. - /// \arg capacity Initial capacity to allocate - vector(count_t capacity) : - m_size(0), - m_capacity(0), - m_elements(nullptr) - { - set_capacity(capacity); - } + /// Constructor. Creates an empty array with capacity. + /// \arg capacity Initial capacity to allocate + vector(count_t capacity) : + m_size(0), + m_capacity(0), + m_elements(nullptr) + { + set_capacity(capacity); + } - /// Copy constructor. Allocates a copy of the other's array. - vector(const vector& other) : - m_size(0), - m_capacity(0), - m_elements(nullptr) - { - set_capacity(other.m_capacity); - kutil::memcpy(m_elements, other.m_elements, other.m_size * sizeof(T)); - m_size = other.m_size; - } + /// Copy constructor. Allocates a copy of the other's array. + vector(const vector& other) : + m_size(0), + m_capacity(0), + m_elements(nullptr) + { + set_capacity(other.m_capacity); + kutil::memcpy(m_elements, other.m_elements, other.m_size * sizeof(T)); + m_size = other.m_size; + } - /// Move constructor. Takes ownership of the other's array. - vector(vector &&other) : - m_size(other.m_size), - m_capacity(other.m_capacity), - m_elements(other.m_elements) - { - other.m_size = 0; - other.m_capacity = 0; - other.m_elements = nullptr; - } + /// Move constructor. Takes ownership of the other's array. + vector(vector &&other) : + m_size(other.m_size), + m_capacity(other.m_capacity), + m_elements(other.m_elements) + { + other.m_size = 0; + other.m_capacity = 0; + other.m_elements = nullptr; + } - /// Static array constructor. Starts the vector off with the given - /// static storage. - vector(T *data, count_t size, count_t capacity) : - m_size(size), - m_capacity(capacity | ~cap_mask), - m_elements(&data[0]) - { - } + /// Static array constructor. Starts the vector off with the given + /// static storage. + vector(T *data, count_t size, count_t capacity) : + m_size(size), + m_capacity(capacity | ~cap_mask), + m_elements(&data[0]) + { + } - /// Destructor. Destroys any remaining items in the array. - ~vector() - { - while (m_size) remove(); + /// Destructor. Destroys any remaining items in the array. + ~vector() + { + while (m_size) remove(); - bool was_static = m_capacity & ~cap_mask; - if (!was_static) - kfree(m_elements); - } + bool was_static = m_capacity & ~cap_mask; + if (!was_static) + kfree(m_elements); + } - /// Get the size of the array. - inline count_t count() const { return m_size; } + /// Get the size of the array. + inline count_t count() const { return m_size; } - /// Get the capacity of the array. This is the amount of space - /// actually allocated. - inline count_t capacity() const { return m_capacity & cap_mask; } + /// Get the capacity of the array. This is the amount of space + /// actually allocated. + inline count_t capacity() const { return m_capacity & cap_mask; } - /// Access an element in the array. - inline T & operator[] (count_t i) { return m_elements[i]; } + /// Access an element in the array. + inline T & operator[] (count_t i) { return m_elements[i]; } - /// Access an element in the array. - inline const T & operator[] (count_t i) const { return m_elements[i]; } + /// Access an element in the array. + inline const T & operator[] (count_t i) const { return m_elements[i]; } - /// Get a pointer to the beginning for iteration. - T * begin() { return m_elements; } + /// Get a pointer to the beginning for iteration. + T * begin() { return m_elements; } - /// Get a pointer to the beginning for iteration. - const T * begin() const { return m_elements; } + /// Get a pointer to the beginning for iteration. + const T * begin() const { return m_elements; } - /// Get a pointer to the end for iteration. - T * end() { return m_elements + m_size; } + /// Get a pointer to the end for iteration. + T * end() { return m_elements + m_size; } - /// Get a pointer to the end for iteration. - const T * end() const { return m_elements + m_size; } + /// Get a pointer to the end for iteration. + const T * end() const { return m_elements + m_size; } - /// Add an item onto the array by copying it. - /// \arg item The item to add - /// \returns A reference to the added item - T & append(const T& item) - { - ensure_capacity(m_size + 1); - m_elements[m_size] = item; - return m_elements[m_size++]; - } + /// Add an item onto the array by copying it. + /// \arg item The item to add + /// \returns A reference to the added item + T & append(const T& item) + { + ensure_capacity(m_size + 1); + m_elements[m_size] = item; + return m_elements[m_size++]; + } - /// Construct an item in place onto the end of the array. - /// \returns A reference to the added item - template - T & emplace(Args&&... args) - { - ensure_capacity(m_size + 1); - new (&m_elements[m_size]) T(std::forward(args)...); - return m_elements[m_size++]; - } + /// Construct an item in place onto the end of the array. + /// \returns A reference to the added item + template + T & emplace(Args&&... args) + { + ensure_capacity(m_size + 1); + new (&m_elements[m_size]) T(std::forward(args)...); + return m_elements[m_size++]; + } - /// Insert an item into the array at the given index - void insert(count_t i, const T& item) - { - if (i >= count()) { - append(item); - return; - } + /// Insert an item into the array at the given index + void insert(count_t i, const T& item) + { + if (i >= count()) { + append(item); + return; + } - ensure_capacity(m_size + 1); - for (count_t j = m_size; j > i; --j) - m_elements[j] = m_elements[j-1]; - m_size += 1; + ensure_capacity(m_size + 1); + for (count_t j = m_size; j > i; --j) + m_elements[j] = m_elements[j-1]; + m_size += 1; - m_elements[i] = item; - } + m_elements[i] = item; + } - /// Insert an item into the list in a sorted position. Depends on T - /// having a method `int compare(const T &other)`. - /// \returns index of the new item - count_t sorted_insert(const T& item) - { - count_t start = 0; - count_t end = m_size; - while (end > start) { - count_t m = start + (end - start) / 2; - int c = item.compare(m_elements[m]); - if (c < 0) end = m; - else start = m + 1; - } + /// Insert an item into the list in a sorted position. Depends on T + /// having a method `int compare(const T &other)`. + /// \returns index of the new item + count_t sorted_insert(const T& item) + { + count_t start = 0; + count_t end = m_size; + while (end > start) { + count_t m = start + (end - start) / 2; + int c = item.compare(m_elements[m]); + if (c < 0) end = m; + else start = m + 1; + } - insert(start, item); - return start; - } + insert(start, item); + return start; + } - /// Remove an item from the end of the array. - void remove() - { - kassert(m_size, "Called remove() on an empty array"); + /// Remove an item from the end of the array. + void remove() + { + kassert(m_size, "Called remove() on an empty array"); - m_size -= 1; - m_elements[m_size].~T(); - } + m_size -= 1; + m_elements[m_size].~T(); + } - /// Remove an item from the front of the array, preserving order. - void remove_front() - { - kassert(m_size, "Called remove_front() on an empty array"); - remove_at(0); - } + /// Remove an item from the front of the array, preserving order. + void remove_front() + { + kassert(m_size, "Called remove_front() on an empty array"); + remove_at(0); + } - /// Remove an item from the array. - void remove(const T &item) - { - kassert(m_size, "Called remove() on an empty array"); - for (count_t i = 0; i < m_size; ++i) { - if (m_elements[i] == item) { - remove_at(i); - break; - } - } - } + /// Remove an item from the array. + void remove(const T &item) + { + kassert(m_size, "Called remove() on an empty array"); + for (count_t i = 0; i < m_size; ++i) { + if (m_elements[i] == item) { + remove_at(i); + break; + } + } + } - /// Remove n items starting at the given index from the array, - /// order-preserving. - void remove_at(count_t i, count_t n = 1) - { - for (count_t j = i; j < i + n; ++j) { - if (j >= m_size) return; - m_elements[j].~T(); - } + /// Remove n items starting at the given index from the array, + /// order-preserving. + void remove_at(count_t i, count_t n = 1) + { + for (count_t j = i; j < i + n; ++j) { + if (j >= m_size) return; + m_elements[j].~T(); + } - for (; i < m_size - n; ++i) - m_elements[i] = m_elements[i+n]; - m_size -= n; - } + for (; i < m_size - n; ++i) + m_elements[i] = m_elements[i+n]; + m_size -= n; + } - /// Remove the first occurance of an item from the array, not - /// order-preserving. Does nothing if the item is not in the array. - void remove_swap(const T &item) - { - for (count_t i = 0; i < m_size; ++i) { - if (m_elements[i] == item) { - remove_swap_at(i); - break; - } - } - } + /// Remove the first occurance of an item from the array, not + /// order-preserving. Does nothing if the item is not in the array. + void remove_swap(const T &item) + { + for (count_t i = 0; i < m_size; ++i) { + if (m_elements[i] == item) { + remove_swap_at(i); + break; + } + } + } - /// Remove the item at the given index from the array, not - /// order-preserving. - void remove_swap_at(count_t i) - { - if (i >= count()) return; + /// Remove the item at the given index from the array, not + /// order-preserving. + void remove_swap_at(count_t i) + { + if (i >= count()) return; - m_elements[i].~T(); - if (i < m_size - 1) - m_elements[i] = m_elements[m_size - 1]; - m_size -= 1; - } + m_elements[i].~T(); + if (i < m_size - 1) + m_elements[i] = m_elements[m_size - 1]; + m_size -= 1; + } - /// Remove an item from the end of the array and return it. - T pop() - { - kassert(m_size, "Called pop() on an empty array"); + /// Remove an item from the end of the array and return it. + T pop() + { + kassert(m_size, "Called pop() on an empty array"); - T temp = m_elements[m_size - 1]; - remove(); - return temp; - } + T temp = m_elements[m_size - 1]; + remove(); + return temp; + } - /// Remove an item from the beginning of the array and return it. - T pop_front() - { - kassert(m_size, "Called pop_front() on an empty array"); + /// Remove an item from the beginning of the array and return it. + T pop_front() + { + kassert(m_size, "Called pop_front() on an empty array"); - T temp = m_elements[0]; - remove_front(); - return temp; - } + T temp = m_elements[0]; + remove_front(); + return temp; + } - /// Set the size of the array. Any new items are default constructed. - /// Any items past the end are deleted. The array is realloced if needed. - /// \arg size The new size - void set_size(count_t size) - { - ensure_capacity(size); - for (count_t i = size; i < m_size; ++i) - m_elements[i].~T(); - for (count_t i = m_size; i < size; ++i) - new (&m_elements[i]) T; - m_size = size; - } + /// Set the size of the array. Any new items are default constructed. + /// Any items past the end are deleted. The array is realloced if needed. + /// \arg size The new size + void set_size(count_t size) + { + ensure_capacity(size); + for (count_t i = size; i < m_size; ++i) + m_elements[i].~T(); + for (count_t i = m_size; i < size; ++i) + new (&m_elements[i]) T; + m_size = size; + } - /// Ensure the array will fit an item. - /// \arg size Size of the array - void ensure_capacity(count_t size) - { - if (capacity() >= size) return; - count_t capacity = (1 << log2(size)); - if (capacity < min_capacity) - capacity = min_capacity; - set_capacity(capacity); - } + /// Ensure the array will fit an item. + /// \arg size Size of the array + void ensure_capacity(count_t size) + { + if (capacity() >= size) return; + count_t capacity = (1 << log2(size)); + if (capacity < min_capacity) + capacity = min_capacity; + set_capacity(capacity); + } - /// Reallocate the array. Copy over any old elements that will - /// fit into the new array. The rest are destroyed. - /// \arg capacity Number of elements to allocate - void set_capacity(count_t capacity) - { - bool was_static = m_capacity & ~cap_mask; - T *new_array = reinterpret_cast(kalloc(capacity * sizeof(T))); - count_t size = capacity > m_size ? m_size : capacity; + /// Reallocate the array. Copy over any old elements that will + /// fit into the new array. The rest are destroyed. + /// \arg capacity Number of elements to allocate + void set_capacity(count_t capacity) + { + bool was_static = m_capacity & ~cap_mask; + T *new_array = reinterpret_cast(kalloc(capacity * sizeof(T))); + count_t size = capacity > m_size ? m_size : capacity; - kutil::memcpy(new_array, m_elements, size * sizeof(T)); + kutil::memcpy(new_array, m_elements, size * sizeof(T)); - while (size < m_size) remove(); - m_size = size; - m_capacity = capacity; + while (size < m_size) remove(); + m_size = size; + m_capacity = capacity; - if (!was_static) - kfree(m_elements); - m_elements = new_array; - } + if (!was_static) + kfree(m_elements); + m_elements = new_array; + } private: - count_t m_size; - count_t m_capacity; - T *m_elements; + count_t m_size; + count_t m_capacity; + T *m_elements; }; } // namespace kutil diff --git a/src/libraries/kutil/logger.cpp b/src/libraries/kutil/logger.cpp index 909deee..3d76aa5 100644 --- a/src/libraries/kutil/logger.cpp +++ b/src/libraries/kutil/logger.cpp @@ -7,8 +7,8 @@ namespace kutil { namespace logs { #define LOG(name, lvl) \ - const log::area_t name = #name ## _h; \ - const char * name ## _name = #name; + const log::area_t name = #name ## _h; \ + const char * name ## _name = #name; #include "j6/tables/log_areas.inc" #undef LOG } @@ -22,28 +22,28 @@ logger *logger::s_log = nullptr; const char *logger::s_level_names[] = {"", "debug", "info", "warn", "error", "fatal"}; logger::logger(logger::immediate_cb output) : - m_buffer(nullptr, 0), - m_immediate(output), - m_flush(nullptr), - m_sequence(0) + m_buffer(nullptr, 0), + m_immediate(output), + m_flush(nullptr), + m_sequence(0) { - memset(&m_levels, 0, sizeof(m_levels)); - memset(&m_names, 0, sizeof(m_names)); - s_log = this; + memset(&m_levels, 0, sizeof(m_levels)); + memset(&m_names, 0, sizeof(m_names)); + s_log = this; } logger::logger(uint8_t *buffer, size_t size, logger::immediate_cb output) : - m_buffer(buffer, size), - m_immediate(output), - m_flush(nullptr), - m_sequence(0) + m_buffer(buffer, size), + m_immediate(output), + m_flush(nullptr), + m_sequence(0) { - memset(&m_levels, 0, sizeof(m_levels)); - memset(&m_names, 0, sizeof(m_names)); - s_log = this; + memset(&m_levels, 0, sizeof(m_levels)); + memset(&m_names, 0, sizeof(m_names)); + s_log = this; #define LOG(name, lvl) \ - register_area(logs::name, logs::name ## _name, log::level::lvl); + register_area(logs::name, logs::name ## _name, log::level::lvl); #include "j6/tables/log_areas.inc" #undef LOG } @@ -51,105 +51,105 @@ logger::logger(uint8_t *buffer, size_t size, logger::immediate_cb output) : void logger::set_level(area_t area, level l) { - unsigned uarea = static_cast(area); - uint8_t ulevel = static_cast(l) & 0x0f; - uint8_t &flags = m_levels[uarea / 2]; - if (uarea & 1) - flags = (flags & 0x0f) | (ulevel << 4); - else - flags = (flags & 0xf0) | ulevel; + unsigned uarea = static_cast(area); + uint8_t ulevel = static_cast(l) & 0x0f; + uint8_t &flags = m_levels[uarea / 2]; + if (uarea & 1) + flags = (flags & 0x0f) | (ulevel << 4); + else + flags = (flags & 0xf0) | ulevel; } level logger::get_level(area_t area) { - unsigned uarea = static_cast(area); - uint8_t &flags = m_levels[uarea / 2]; - if (uarea & 1) - return static_cast((flags & 0xf0) >> 4); - else - return static_cast(flags & 0x0f); + unsigned uarea = static_cast(area); + uint8_t &flags = m_levels[uarea / 2]; + if (uarea & 1) + return static_cast((flags & 0xf0) >> 4); + else + return static_cast(flags & 0x0f); } void logger::register_area(area_t area, const char *name, level verbosity) { - m_names[area] = name; - set_level(area, verbosity); + m_names[area] = name; + set_level(area, verbosity); } void logger::output(level severity, area_t area, const char *fmt, va_list args) { - uint8_t buffer[256]; - entry *header = reinterpret_cast(buffer); - header->bytes = sizeof(entry); - header->area = area; - header->severity = severity; - header->sequence = m_sequence++; + uint8_t buffer[256]; + entry *header = reinterpret_cast(buffer); + header->bytes = sizeof(entry); + header->area = area; + header->severity = severity; + header->sequence = m_sequence++; - header->bytes += - vsnprintf(header->message, sizeof(buffer) - sizeof(entry), fmt, args); + header->bytes += + vsnprintf(header->message, sizeof(buffer) - sizeof(entry), fmt, args); - kutil::scoped_lock lock {m_lock}; + kutil::scoped_lock lock {m_lock}; - if (m_immediate) { - buffer[header->bytes] = 0; - m_immediate(area, severity, header->message); - return; - } + if (m_immediate) { + buffer[header->bytes] = 0; + m_immediate(area, severity, header->message); + return; + } - uint8_t *out; - size_t n = m_buffer.reserve(header->bytes, reinterpret_cast(&out)); - if (n < sizeof(entry)) { - m_buffer.commit(0); // Cannot even write the header, abort - return; - } + uint8_t *out; + size_t n = m_buffer.reserve(header->bytes, reinterpret_cast(&out)); + if (n < sizeof(entry)) { + m_buffer.commit(0); // Cannot even write the header, abort + return; + } - if (n < header->bytes) - header->bytes = n; + if (n < header->bytes) + header->bytes = n; - memcpy(out, buffer, n); - m_buffer.commit(n); + memcpy(out, buffer, n); + m_buffer.commit(n); - if (m_flush) - m_flush(); + if (m_flush) + m_flush(); } size_t logger::get_entry(void *buffer, size_t size) { - kutil::scoped_lock lock {m_lock}; + kutil::scoped_lock lock {m_lock}; - void *out; - size_t out_size = m_buffer.get_block(&out); - if (out_size == 0 || out == 0) - return 0; + void *out; + size_t out_size = m_buffer.get_block(&out); + if (out_size == 0 || out == 0) + return 0; - kassert(out_size >= sizeof(entry), "Couldn't read a full entry"); - if (out_size < sizeof(entry)) - return 0; + kassert(out_size >= sizeof(entry), "Couldn't read a full entry"); + if (out_size < sizeof(entry)) + return 0; - entry *ent = reinterpret_cast(out); - if (size >= ent->bytes) { - memcpy(buffer, out, ent->bytes); - m_buffer.consume(ent->bytes); - } + entry *ent = reinterpret_cast(out); + if (size >= ent->bytes) { + memcpy(buffer, out, ent->bytes); + m_buffer.consume(ent->bytes); + } - return ent->bytes; + return ent->bytes; } #define LOG_LEVEL_FUNCTION(name) \ - void name (area_t area, const char *fmt, ...) { \ - logger *l = logger::s_log; \ - if (!l) return; \ - level limit = l->get_level(area); \ - if (limit == level::none || level::name < limit) return; \ - va_list args; \ - va_start(args, fmt); \ - l->output(level::name, area, fmt, args); \ - va_end(args); \ - } + void name (area_t area, const char *fmt, ...) { \ + logger *l = logger::s_log; \ + if (!l) return; \ + level limit = l->get_level(area); \ + if (limit == level::none || level::name < limit) return; \ + va_list args; \ + va_start(args, fmt); \ + l->output(level::name, area, fmt, args); \ + va_end(args); \ + } LOG_LEVEL_FUNCTION(debug); LOG_LEVEL_FUNCTION(info); @@ -158,15 +158,15 @@ LOG_LEVEL_FUNCTION(error); void fatal(area_t area, const char *fmt, ...) { - logger *l = logger::s_log; - if (!l) return; + logger *l = logger::s_log; + if (!l) return; - va_list args; - va_start(args, fmt); - l->output(level::fatal, area, fmt, args); - va_end(args); + va_list args; + va_start(args, fmt); + l->output(level::fatal, area, fmt, args); + va_end(args); - kassert(false, "log::fatal"); + kassert(false, "log::fatal"); } } // namespace log diff --git a/src/libraries/kutil/memory.cpp b/src/libraries/kutil/memory.cpp index 451e492..149435e 100644 --- a/src/libraries/kutil/memory.cpp +++ b/src/libraries/kutil/memory.cpp @@ -1,7 +1,7 @@ #include "kutil/memory.h" namespace std { - enum class __attribute__ ((__type_visibility("default"))) align_val_t : size_t { }; + enum class __attribute__ ((__type_visibility("default"))) align_val_t : size_t { }; } namespace kutil { @@ -9,27 +9,27 @@ namespace kutil { void * memset(void *s, uint8_t v, size_t n) { - uint8_t *p = reinterpret_cast(s); - for (size_t i = 0; i < n; ++i) p[i] = v; - return s; + uint8_t *p = reinterpret_cast(s); + for (size_t i = 0; i < n; ++i) p[i] = v; + return s; } void * memcpy(void *dest, const void *src, size_t n) { - const uint8_t *s = reinterpret_cast(src); - uint8_t *d = reinterpret_cast(dest); - for (size_t i = 0; i < n; ++i) d[i] = s[i]; - return d; + const uint8_t *s = reinterpret_cast(src); + uint8_t *d = reinterpret_cast(dest); + for (size_t i = 0; i < n; ++i) d[i] = s[i]; + return d; } uint8_t checksum(const void *p, size_t len, size_t off) { - uint8_t sum = 0; - const uint8_t *c = reinterpret_cast(p); - for (int i = off; i < len; ++i) sum += c[i]; - return sum; + uint8_t sum = 0; + const uint8_t *c = reinterpret_cast(p); + for (int i = off; i < len; ++i) sum += c[i]; + return sum; } } // namespace kutil diff --git a/src/libraries/kutil/spinlock.cpp b/src/libraries/kutil/spinlock.cpp index 73b57de..c31b086 100644 --- a/src/libraries/kutil/spinlock.cpp +++ b/src/libraries/kutil/spinlock.cpp @@ -10,36 +10,36 @@ spinlock::~spinlock() {} void spinlock::acquire(waiter *w) { - w->next = nullptr; - w->blocked = true; + w->next = nullptr; + w->blocked = true; - // Point the lock at this waiter - waiter *prev = __atomic_exchange_n(&m_lock, w, memorder); - if (prev) { - // If there was a previous waiter, wait for them to - // unblock us - prev->next = w; - while (w->blocked) - asm ("pause"); - } else { - w->blocked = false; - } + // Point the lock at this waiter + waiter *prev = __atomic_exchange_n(&m_lock, w, memorder); + if (prev) { + // If there was a previous waiter, wait for them to + // unblock us + prev->next = w; + while (w->blocked) + asm ("pause"); + } else { + w->blocked = false; + } } void spinlock::release(waiter *w) { - // If we're still the last waiter, we're done - waiter *expected = w; - if(__atomic_compare_exchange_n(&m_lock, &expected, nullptr, false, memorder, memorder)) - return; + // If we're still the last waiter, we're done + waiter *expected = w; + if(__atomic_compare_exchange_n(&m_lock, &expected, nullptr, false, memorder, memorder)) + return; - // Wait for the subseqent waiter to tell us who they are - while (!w->next) - asm ("pause"); + // Wait for the subseqent waiter to tell us who they are + while (!w->next) + asm ("pause"); - // Unblock the subseqent waiter - w->next->blocked = false; + // Unblock the subseqent waiter + w->next->blocked = false; } diff --git a/src/libraries/libc/tests/_PDCLIB_test.h b/src/libraries/libc/tests/_PDCLIB_test.h index 8e5dcd0..2ce525c 100644 --- a/src/libraries/libc/tests/_PDCLIB_test.h +++ b/src/libraries/libc/tests/_PDCLIB_test.h @@ -51,51 +51,51 @@ pid_t waitpid(pid_t, int *, int); void _exit(int); #define START_SUITE(name) \ - int run_suite_ ##name (void) { \ - int TEST_RESULTS = 0; + int run_suite_ ##name (void) { \ + int TEST_RESULTS = 0; #define END_SUITE \ - return TEST_RESULTS; \ - } + return TEST_RESULTS; \ + } #define DECLARE_SUITE(name) extern int run_suite_ ##name (void) #define RUN_TEST(name) TEST_RESULTS += test__ ##name(); #define START_TEST(name) \ - int test__ ##name (void) { \ - int TEST_RESULTS = 0; + int test__ ##name (void) { \ + int TEST_RESULTS = 0; #define END_TEST \ - return TEST_RESULTS; \ - } + return TEST_RESULTS; \ + } /* TESTCASE() - generic test */ #define TESTCASE( x ) \ - do { \ - pid_t pid = fork(); \ - if ( !pid ) _exit((x) ? 0 : 0xFF); \ + do { \ + pid_t pid = fork(); \ + if ( !pid ) _exit((x) ? 0 : 0xFF); \ else { \ - int __rc = 0; \ - waitpid(pid, &__rc, 0); \ - if ( __rc & 0xff00 ) { \ - TEST_RESULTS += 1; \ - fprintf( stderr, "FAILED: " __FILE__ ":%s, line %d - %s\n", __func__, __LINE__, #x ); \ - } \ - } \ - } while(0) + int __rc = 0; \ + waitpid(pid, &__rc, 0); \ + if ( __rc & 0xff00 ) { \ + TEST_RESULTS += 1; \ + fprintf( stderr, "FAILED: " __FILE__ ":%s, line %d - %s\n", __func__, __LINE__, #x ); \ + } \ + } \ + } while(0) /* TESTCASE_REQUIRE() - must-pass test; return early otherwise */ #define TESTCASE_REQUIRE( x ) \ - do { \ - pid_t pid = fork(); \ - if ( !pid ) _exit((x) ? 0 : 0xFF); \ + do { \ + pid_t pid = fork(); \ + if ( !pid ) _exit((x) ? 0 : 0xFF); \ else { \ - int __rc = 0; \ - waitpid(pid, &__rc, 0); \ - if ( __rc & 0xff00 ) { \ - TEST_RESULTS += 1; \ - fprintf( stderr, "FAILED: " __FILE__ ":%s, line %d - %s\n", __func__, __LINE__, #x ); \ - return TEST_RESULTS; \ - } \ - } \ - } while(0) + int __rc = 0; \ + waitpid(pid, &__rc, 0); \ + if ( __rc & 0xff00 ) { \ + TEST_RESULTS += 1; \ + fprintf( stderr, "FAILED: " __FILE__ ":%s, line %d - %s\n", __func__, __LINE__, #x ); \ + return TEST_RESULTS; \ + } \ + } \ + } while(0) diff --git a/src/libraries/libc/tests/printf_testcases.h b/src/libraries/libc/tests/printf_testcases.h index 45bcf53..68159df 100644 --- a/src/libraries/libc/tests/printf_testcases.h +++ b/src/libraries/libc/tests/printf_testcases.h @@ -1,6 +1,6 @@ #define PRINTF_TEST( expected_rc, expected_string, ... ) do { \ - TEST_RESULTS += DO_TESTPRINTF(IMPLFILE, __FILE__, __LINE__, expected_rc, expected_string, __VA_ARGS__); \ - } while (0); + TEST_RESULTS += DO_TESTPRINTF(IMPLFILE, __FILE__, __LINE__, expected_rc, expected_string, __VA_ARGS__); \ + } while (0); { diff --git a/src/libraries/libc/tests/scanf_testcases.h b/src/libraries/libc/tests/scanf_testcases.h index e654724..2ff2471 100644 --- a/src/libraries/libc/tests/scanf_testcases.h +++ b/src/libraries/libc/tests/scanf_testcases.h @@ -1,6 +1,6 @@ #define SCANF_TEST( expected_rc, input_string, ... ) do { \ - TEST_RESULTS += DO_TESTSCANF(IMPLFILE, __FILE__, __LINE__, expected_rc, input_string, __VA_ARGS__); \ - } while (0); + TEST_RESULTS += DO_TESTSCANF(IMPLFILE, __FILE__, __LINE__, expected_rc, input_string, __VA_ARGS__); \ + } while (0); { char buffer[100]; diff --git a/src/tests/constexpr_hash.cpp b/src/tests/constexpr_hash.cpp index 6c62f14..534647e 100644 --- a/src/tests/constexpr_hash.cpp +++ b/src/tests/constexpr_hash.cpp @@ -5,17 +5,17 @@ using namespace kutil; TEST_CASE( "constexpr hash", "[hash]" ) { - const unsigned hash1 = static_cast("hash1!"_h); - CHECK(hash1 == 210); + const unsigned hash1 = static_cast("hash1!"_h); + CHECK(hash1 == 210); - const unsigned hash2 = static_cast("hash1!"_h); - CHECK(hash1 == hash2); + const unsigned hash2 = static_cast("hash1!"_h); + CHECK(hash1 == hash2); - const unsigned hash3 = static_cast("not hash1!"_h); - CHECK(hash1 != hash3); - CHECK(hash3 == 37); + const unsigned hash3 = static_cast("not hash1!"_h); + CHECK(hash1 != hash3); + CHECK(hash3 == 37); - const unsigned hash4 = static_cast("another thing that's longer"_h); - CHECK(hash1 != hash4); - CHECK(hash4 == 212); + const unsigned hash4 = static_cast("another thing that's longer"_h); + CHECK(hash1 != hash4); + CHECK(hash4 == 212); } diff --git a/src/tests/container_helpers.h b/src/tests/container_helpers.h index 335dd9e..5643bce 100644 --- a/src/tests/container_helpers.h +++ b/src/tests/container_helpers.h @@ -1,13 +1,13 @@ #pragma once struct unsortableT { - int value; + int value; }; struct sortableT { - int value; - int compare(const sortableT &other) const { - return value - other.value; - } + int value; + int compare(const sortableT &other) const { + return value - other.value; + } }; diff --git a/src/tests/heap_allocator.cpp b/src/tests/heap_allocator.cpp index b88e719..a2a1efb 100644 --- a/src/tests/heap_allocator.cpp +++ b/src/tests/heap_allocator.cpp @@ -26,169 +26,169 @@ extern bool ASSERT_EXPECTED; extern bool ASSERT_HAPPENED; std::vector sizes = { - 16000, 8000, 4000, 4000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 150, - 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 48, 48, 48, 13 }; + 16000, 8000, 4000, 4000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 48, 48, 48, 13 }; void segfault_handler(int signum, siginfo_t *info, void *ctxp) { - uintptr_t start = reinterpret_cast(mem_base); - uintptr_t end = start + mem_size; - uintptr_t addr = reinterpret_cast(info->si_addr); + uintptr_t start = reinterpret_cast(mem_base); + uintptr_t end = start + mem_size; + uintptr_t addr = reinterpret_cast(info->si_addr); - if (addr < start || addr >= end) { - CAPTURE( start ); - CAPTURE( end ); - CAPTURE( addr ); - FAIL("Segfaulted outside memory area"); - } + if (addr < start || addr >= end) { + CAPTURE( start ); + CAPTURE( end ); + CAPTURE( addr ); + FAIL("Segfaulted outside memory area"); + } - signalled_at = info->si_addr; - signalled += 1; - if (mprotect(signalled_at, max_block, PROT_READ|PROT_WRITE)) { - perror("mprotect"); - exit(100); - } + signalled_at = info->si_addr; + signalled += 1; + if (mprotect(signalled_at, max_block, PROT_READ|PROT_WRITE)) { + perror("mprotect"); + exit(100); + } } TEST_CASE( "Buddy blocks tests", "[memory buddy]" ) { - using clock = std::chrono::system_clock; - unsigned seed = clock::now().time_since_epoch().count(); - std::default_random_engine rng(seed); + using clock = std::chrono::system_clock; + unsigned seed = clock::now().time_since_epoch().count(); + std::default_random_engine rng(seed); - mem_base = aligned_alloc(max_block, mem_size); + mem_base = aligned_alloc(max_block, mem_size); - // Catch segfaults so we can track memory access - struct sigaction sigact; - memset(&sigact, 0, sizeof(sigact)); - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = SA_NODEFER|SA_SIGINFO; - sigact.sa_sigaction = segfault_handler; - sigaction(SIGSEGV, &sigact, nullptr); + // Catch segfaults so we can track memory access + struct sigaction sigact; + memset(&sigact, 0, sizeof(sigact)); + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = SA_NODEFER|SA_SIGINFO; + sigact.sa_sigaction = segfault_handler; + sigaction(SIGSEGV, &sigact, nullptr); - // Protect our memory arena so we trigger out fault handler - REQUIRE( mprotect(mem_base, max_block*4, PROT_NONE) == 0 ); + // Protect our memory arena so we trigger out fault handler + REQUIRE( mprotect(mem_base, max_block*4, PROT_NONE) == 0 ); - heap_allocator mm( - reinterpret_cast(mem_base), - max_block * 4); + heap_allocator mm( + reinterpret_cast(mem_base), + max_block * 4); - // Initial creation should not have allocated - CHECK( signalled == 0 ); - signalled = 0; + // Initial creation should not have allocated + CHECK( signalled == 0 ); + signalled = 0; - // Allocating too much should assert - ASSERT_EXPECTED = true; - void *p = mm.allocate(max_block - hs + 1); - REQUIRE( ASSERT_HAPPENED ); - ASSERT_HAPPENED = false; + // Allocating too much should assert + ASSERT_EXPECTED = true; + void *p = mm.allocate(max_block - hs + 1); + REQUIRE( ASSERT_HAPPENED ); + ASSERT_HAPPENED = false; - // Allocating should signal just at the first page. - p = mm.allocate(max_block - hs); - CHECK( p == offset_pointer(mem_base, hs) ); - CHECK( signalled == 1 ); - CHECK( signalled_at == mem_base ); - signalled = 0; + // Allocating should signal just at the first page. + p = mm.allocate(max_block - hs); + CHECK( p == offset_pointer(mem_base, hs) ); + CHECK( signalled == 1 ); + CHECK( signalled_at == mem_base ); + signalled = 0; - // Freeing and allocating should not allocate - mm.free(p); - p = mm.allocate(max_block - hs); - CHECK( p == offset_pointer(mem_base, hs) ); - CHECK( signalled == 0 ); - signalled = 0; + // Freeing and allocating should not allocate + mm.free(p); + p = mm.allocate(max_block - hs); + CHECK( p == offset_pointer(mem_base, hs) ); + CHECK( signalled == 0 ); + signalled = 0; - mm.free(p); - CHECK( signalled == 0 ); - signalled = 0; + mm.free(p); + CHECK( signalled == 0 ); + signalled = 0; - // Blocks should be: - // 22: 0-4M + // Blocks should be: + // 22: 0-4M - std::vector allocs(6); - for (int i = 0; i < 6; ++i) - allocs[i] = mm.allocate(150); // size 8 + std::vector allocs(6); + for (int i = 0; i < 6; ++i) + allocs[i] = mm.allocate(150); // size 8 - // Should not have grown - CHECK( signalled == 0 ); - signalled = 0; + // Should not have grown + CHECK( signalled == 0 ); + signalled = 0; - // Blocks should be: - // 22: [0-4M] - // 21: [0-2M], 2-4M - // 20: [0-1M], 1-2M - // 19: [0-512K], 512K-1M - // 18: [0-256K], 256-512K - // 17: [0-128K], 128-256K - // 16: [0-64K], 64-128K - // 15: [0-32K], 32K-64K - // 14: [0-16K], 16K-32K - // 13: [0-8K], 8K-16K - // 12: [0-4K], 4K-8K - // 11: [0-2K], 2K-4K - // 10: [0-1K, 1-2K] - // 9: [0, 512, 1024], 1536 - // 8: [0, 256, 512, 768, 1024, 1280] + // Blocks should be: + // 22: [0-4M] + // 21: [0-2M], 2-4M + // 20: [0-1M], 1-2M + // 19: [0-512K], 512K-1M + // 18: [0-256K], 256-512K + // 17: [0-128K], 128-256K + // 16: [0-64K], 64-128K + // 15: [0-32K], 32K-64K + // 14: [0-16K], 16K-32K + // 13: [0-8K], 8K-16K + // 12: [0-4K], 4K-8K + // 11: [0-2K], 2K-4K + // 10: [0-1K, 1-2K] + // 9: [0, 512, 1024], 1536 + // 8: [0, 256, 512, 768, 1024, 1280] - // We have free memory at 1526 and 2K, but we should get 4K - void *big = mm.allocate(4000); // size 12 + // We have free memory at 1526 and 2K, but we should get 4K + void *big = mm.allocate(4000); // size 12 - CHECK( signalled == 0 ); - signalled = 0; + CHECK( signalled == 0 ); + signalled = 0; - REQUIRE( big == offset_pointer(mem_base, 4096 + hs) ); - mm.free(big); + REQUIRE( big == offset_pointer(mem_base, 4096 + hs) ); + mm.free(big); - // free up 512 - mm.free(allocs[3]); - mm.free(allocs[4]); + // free up 512 + mm.free(allocs[3]); + mm.free(allocs[4]); - // Blocks should be: - // ... - // 9: [0, 512, 1024], 1536 - // 8: [0, 256, 512], 768, 1024, [1280] + // Blocks should be: + // ... + // 9: [0, 512, 1024], 1536 + // 8: [0, 256, 512], 768, 1024, [1280] - // A request for a 512-block should not cross the buddy divide - big = mm.allocate(500); // size 9 - REQUIRE( big >= offset_pointer(mem_base, 1536 + hs) ); - mm.free(big); + // A request for a 512-block should not cross the buddy divide + big = mm.allocate(500); // size 9 + REQUIRE( big >= offset_pointer(mem_base, 1536 + hs) ); + mm.free(big); - mm.free(allocs[0]); - mm.free(allocs[1]); - mm.free(allocs[2]); - mm.free(allocs[5]); - allocs.clear(); + mm.free(allocs[0]); + mm.free(allocs[1]); + mm.free(allocs[2]); + mm.free(allocs[5]); + allocs.clear(); - std::shuffle(sizes.begin(), sizes.end(), rng); + std::shuffle(sizes.begin(), sizes.end(), rng); - allocs.reserve(sizes.size()); - for (size_t size : sizes) - allocs.push_back(mm.allocate(size)); + allocs.reserve(sizes.size()); + for (size_t size : sizes) + allocs.push_back(mm.allocate(size)); - std::shuffle(allocs.begin(), allocs.end(), rng); - for (void *p: allocs) - mm.free(p); - allocs.clear(); + std::shuffle(allocs.begin(), allocs.end(), rng); + for (void *p: allocs) + mm.free(p); + allocs.clear(); - big = mm.allocate(max_block / 2 + 1); + big = mm.allocate(max_block / 2 + 1); - // If everything was freed / joined correctly, that should not have allocated - CHECK( signalled == 0 ); - signalled = 0; + // If everything was freed / joined correctly, that should not have allocated + CHECK( signalled == 0 ); + signalled = 0; - // And we should have gotten back the start of memory - CHECK( big == offset_pointer(mem_base, hs) ); + // And we should have gotten back the start of memory + CHECK( big == offset_pointer(mem_base, hs) ); - // Allocating again should signal at the next page. - void *p2 = mm.allocate(max_block - hs); - CHECK( p2 == offset_pointer(mem_base, max_block + hs) ); - CHECK( signalled == 1 ); - CHECK( signalled_at == offset_pointer(mem_base, max_block) ); - signalled = 0; + // Allocating again should signal at the next page. + void *p2 = mm.allocate(max_block - hs); + CHECK( p2 == offset_pointer(mem_base, max_block + hs) ); + CHECK( signalled == 1 ); + CHECK( signalled_at == offset_pointer(mem_base, max_block) ); + signalled = 0; - mm.free(p2); - CHECK( signalled == 0 ); - signalled = 0; + mm.free(p2); + CHECK( signalled == 0 ); + signalled = 0; - free(mem_base); + free(mem_base); } diff --git a/src/tests/linked_list.cpp b/src/tests/linked_list.cpp index 6f28f56..4b30c81 100644 --- a/src/tests/linked_list.cpp +++ b/src/tests/linked_list.cpp @@ -13,142 +13,142 @@ const int test_list_size = 100; template class ListVectorCompare : - public Catch::MatcherBase>> + public Catch::MatcherBase>> { public: - using item = list_node; - using vector = std::vector; + using item = list_node; + using vector = std::vector; - ListVectorCompare(const linked_list &list, bool reversed) : - m_list(list), m_reverse(reversed) {} + ListVectorCompare(const linked_list &list, bool reversed) : + m_list(list), m_reverse(reversed) {} - virtual bool match (vector const& vec) const override - { - size_t index = m_reverse ? vec.size() - 1 : 0; - for (const T *i : m_list) { - if (i != &vec[index]) return false; - index += m_reverse ? -1 : 1; - } - return true; - } + virtual bool match (vector const& vec) const override + { + size_t index = m_reverse ? vec.size() - 1 : 0; + for (const T *i : m_list) { + if (i != &vec[index]) return false; + index += m_reverse ? -1 : 1; + } + return true; + } - virtual std::string describe() const override - { - return "is the same as the given linked list"; - } + virtual std::string describe() const override + { + return "is the same as the given linked list"; + } private: - const linked_list &m_list; - bool m_reverse; + const linked_list &m_list; + bool m_reverse; }; template class IsSorted : - public Catch::MatcherBase> + public Catch::MatcherBase> { public: - using item = list_node; - using list = linked_list; + using item = list_node; + using list = linked_list; - IsSorted() {} + IsSorted() {} - virtual bool match (list const& l) const override - { - int big = std::numeric_limits::min(); - for (const T *i : l) { - if (i->value < big) return false; - big = i->value; - } - return true; - } + virtual bool match (list const& l) const override + { + int big = std::numeric_limits::min(); + for (const T *i : l) { + if (i->value < big) return false; + big = i->value; + } + return true; + } - virtual std::string describe() const override - { - return "is sorted"; - } + virtual std::string describe() const override + { + return "is sorted"; + } }; template class ListContainsMatcher : - public Catch::MatcherBase> + public Catch::MatcherBase> { public: - using item = list_node; - using list = linked_list; + using item = list_node; + using list = linked_list; - ListContainsMatcher(const item &needle) : m_needle(needle) {} + ListContainsMatcher(const item &needle) : m_needle(needle) {} - virtual bool match (list const& l) const override - { - for (const T *i : l) - if (i == &m_needle) return true; - return false; - } + virtual bool match (list const& l) const override + { + for (const T *i : l) + if (i == &m_needle) return true; + return false; + } - virtual std::string describe() const override - { - return "contains the given item"; - } + virtual std::string describe() const override + { + return "contains the given item"; + } - const item &m_needle; + const item &m_needle; }; template ListVectorCompare IsSameAsList(const linked_list &list, bool reversed = false) { - return ListVectorCompare(list, reversed); + return ListVectorCompare(list, reversed); } template ListContainsMatcher ListContains(const list_node &item) { - return ListContainsMatcher(item); + return ListContainsMatcher(item); } TEST_CASE( "Linked list tests", "[containers] [list]" ) { - linked_list ulist; + linked_list ulist; - int value = 0; - std::vector> unsortables(test_list_size); - for (auto &i : unsortables) { - i.value = value++; - ulist.push_back(&i); - } - CHECK( ulist.length() == test_list_size ); - CHECK_THAT( unsortables, IsSameAsList(ulist) ); + int value = 0; + std::vector> unsortables(test_list_size); + for (auto &i : unsortables) { + i.value = value++; + ulist.push_back(&i); + } + CHECK( ulist.length() == test_list_size ); + CHECK_THAT( unsortables, IsSameAsList(ulist) ); - linked_list ulist_reversed; + linked_list ulist_reversed; - for (auto &i : unsortables) { - ulist.remove(&i); - ulist_reversed.push_front(&i); - } + for (auto &i : unsortables) { + ulist.remove(&i); + ulist_reversed.push_front(&i); + } - CHECK( ulist_reversed.length() == test_list_size ); - CHECK_THAT( unsortables, IsSameAsList(ulist_reversed, true) ); + CHECK( ulist_reversed.length() == test_list_size ); + CHECK_THAT( unsortables, IsSameAsList(ulist_reversed, true) ); - auto &removed = unsortables[test_list_size / 2]; - ulist_reversed.remove(&removed); - CHECK( ulist_reversed.length() == test_list_size - 1 ); - CHECK_THAT( ulist_reversed, !ListContains(removed) ); + auto &removed = unsortables[test_list_size / 2]; + ulist_reversed.remove(&removed); + CHECK( ulist_reversed.length() == test_list_size - 1 ); + CHECK_THAT( ulist_reversed, !ListContains(removed) ); } TEST_CASE( "Sorted list tests", "[containers] [list]" ) { - using clock = std::chrono::system_clock; - unsigned seed = clock::now().time_since_epoch().count(); - std::default_random_engine rng(seed); - std::uniform_int_distribution gen(1, 1000); + using clock = std::chrono::system_clock; + unsigned seed = clock::now().time_since_epoch().count(); + std::default_random_engine rng(seed); + std::uniform_int_distribution gen(1, 1000); - linked_list slist; - CHECK( slist.length() == 0 ); + linked_list slist; + CHECK( slist.length() == 0 ); - std::vector> sortables(test_list_size); - for (auto &i : sortables) { - i.value = gen(rng); - slist.sorted_insert(&i); - } - CHECK( slist.length() == test_list_size ); - CHECK_THAT( slist, IsSorted() ); + std::vector> sortables(test_list_size); + for (auto &i : sortables) { + i.value = gen(rng); + slist.sorted_insert(&i); + } + CHECK( slist.length() == test_list_size ); + CHECK_THAT( slist, IsSorted() ); } diff --git a/src/tests/logger.cpp b/src/tests/logger.cpp index 8a6a2dc..4b53da7 100644 --- a/src/tests/logger.cpp +++ b/src/tests/logger.cpp @@ -14,19 +14,19 @@ log::area_t hash2 = "test_area2"_h; TEST_CASE( "logger writing", "[logger]" ) { - log::logger logger(test_log_buffer, sizeof(test_log_buffer)); - logger.register_area(hash1, name1, log::level::debug); - logger.register_area(hash2, name2, log::level::debug); - CHECK( hash1 != hash2 ); + log::logger logger(test_log_buffer, sizeof(test_log_buffer)); + logger.register_area(hash1, name1, log::level::debug); + logger.register_area(hash2, name2, log::level::debug); + CHECK( hash1 != hash2 ); - const char *check1 = logger.area_name(hash1); - const char *check2 = logger.area_name(hash2); + const char *check1 = logger.area_name(hash1); + const char *check2 = logger.area_name(hash2); - CHECK( check1 == name1 ); - CHECK( check2 == name2 ); + CHECK( check1 == name1 ); + CHECK( check2 == name2 ); - log::debug(hash1, "This is a thing %016lx", 35); - log::info(hash2, "This is a string %s", "foo"); - log::warn(hash1, "This is a thing %016lx", 682); - log::error(hash2, "This is a string %s", "bar"); + log::debug(hash1, "This is a thing %016lx", 35); + log::info(hash2, "This is a string %s", "foo"); + log::warn(hash1, "This is a thing %016lx", 682); + log::error(hash2, "This is a string %s", "bar"); } diff --git a/src/tests/main.cpp b/src/tests/main.cpp index cb2d4e2..d4a4c30 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -7,20 +7,20 @@ bool ASSERT_EXPECTED = false; bool ASSERT_HAPPENED = false; void test_assert(const char *file, unsigned line, const char *message) { - CAPTURE( file ); - CAPTURE( line ); - INFO( message ); - REQUIRE( ASSERT_EXPECTED ); - ASSERT_EXPECTED = false; - ASSERT_HAPPENED = true; + CAPTURE( file ); + CAPTURE( line ); + INFO( message ); + REQUIRE( ASSERT_EXPECTED ); + ASSERT_EXPECTED = false; + ASSERT_HAPPENED = true; } int main( int argc, char* argv[] ) { - kutil::assert_set_callback(test_assert); + kutil::assert_set_callback(test_assert); - int result = Catch::Session().run( argc, argv ); - return result; + int result = Catch::Session().run( argc, argv ); + return result; } namespace kutil { diff --git a/src/tests/map.cpp b/src/tests/map.cpp index 602c179..41eb418 100644 --- a/src/tests/map.cpp +++ b/src/tests/map.cpp @@ -6,90 +6,90 @@ std::uniform_int_distribution distrib {0, 10000}; TEST_CASE( "map insertion", "[containers] [map]" ) { - std::vector ints; - for (int i = 0; i < 1000; ++i) - ints.push_back(i); + std::vector ints; + for (int i = 0; i < 1000; ++i) + ints.push_back(i); - size_t sizes[] = {1, 2, 3, 5, 100}; - for (size_t s : sizes) { - kutil::map v; - std::shuffle(ints.begin(), ints.end(), rng()); + size_t sizes[] = {1, 2, 3, 5, 100}; + for (size_t s : sizes) { + kutil::map v; + std::shuffle(ints.begin(), ints.end(), rng()); - for (int i = 0; i < s; ++i) { - v.insert(ints[i], ints[i]); - } + for (int i = 0; i < s; ++i) { + v.insert(ints[i], ints[i]); + } - for (int i = 0; i < s; ++i) { - int *p = v.find(ints[i]); - CAPTURE( s ); - CAPTURE( i ); - CAPTURE( ints[i] ); - CAPTURE( kutil::hash(ints[i]) ); - CHECK( p ); - CHECK( *p == ints[i] ); - } - } + for (int i = 0; i < s; ++i) { + int *p = v.find(ints[i]); + CAPTURE( s ); + CAPTURE( i ); + CAPTURE( ints[i] ); + CAPTURE( kutil::hash(ints[i]) ); + CHECK( p ); + CHECK( *p == ints[i] ); + } + } } TEST_CASE( "map deletion", "[containers] [map]" ) { - std::vector ints; - for (int i = 0; i < 1000; ++i) - ints.push_back(i); + std::vector ints; + for (int i = 0; i < 1000; ++i) + ints.push_back(i); - size_t sizes[] = {1, 2, 3, 5, 100}; - for (size_t s : sizes) { - kutil::map v; - std::shuffle(ints.begin(), ints.end(), rng()); + size_t sizes[] = {1, 2, 3, 5, 100}; + for (size_t s : sizes) { + kutil::map v; + std::shuffle(ints.begin(), ints.end(), rng()); - for (int i = 0; i < s; ++i) { - v.insert(ints[i], ints[i]); - } + for (int i = 0; i < s; ++i) { + v.insert(ints[i], ints[i]); + } - for (int i = 0; i < s; i += 2) { - v.erase(ints[i]); - } + for (int i = 0; i < s; i += 2) { + v.erase(ints[i]); + } - for (int i = 0; i < s; ++i) { - int *p = v.find(ints[i]); - CAPTURE( s ); - CAPTURE( i ); - CAPTURE( ints[i] ); - CAPTURE( kutil::hash(ints[i]) ); - if ( i%2 ) - CHECK( p ); - else - CHECK( !p ); - } - } + for (int i = 0; i < s; ++i) { + int *p = v.find(ints[i]); + CAPTURE( s ); + CAPTURE( i ); + CAPTURE( ints[i] ); + CAPTURE( kutil::hash(ints[i]) ); + if ( i%2 ) + CHECK( p ); + else + CHECK( !p ); + } + } } TEST_CASE( "map with pointer vals", "[containers] [map]" ) { - kutil::map v; - int is[4] = { 0, 0, 0, 0 }; - for (int i = 0; i < 4; ++i) - v.insert(i*7, &is[i]); + kutil::map v; + int is[4] = { 0, 0, 0, 0 }; + for (int i = 0; i < 4; ++i) + v.insert(i*7, &is[i]); - for (int i = 0; i < 4; ++i) { - int *p = v.find(i*7); - CHECK( p == &is[i] ); - } + for (int i = 0; i < 4; ++i) { + int *p = v.find(i*7); + CHECK( p == &is[i] ); + } - CHECK( v.find(3) == nullptr ); + CHECK( v.find(3) == nullptr ); } TEST_CASE( "map with uint64_t keys", "[containers] [map]" ) { - kutil::map v; - int is[4] = { 2, 3, 5, 7 }; - for (uint64_t i = 0; i < 4; ++i) - v.insert(i+1, is[i]); + kutil::map v; + int is[4] = { 2, 3, 5, 7 }; + for (uint64_t i = 0; i < 4; ++i) + v.insert(i+1, is[i]); - for (uint64_t i = 0; i < 4; ++i) { - int *p = v.find(i+1); - CHECK( *p == is[i] ); - } + for (uint64_t i = 0; i < 4; ++i) { + int *p = v.find(i+1); + CHECK( *p == is[i] ); + } - CHECK( v.find(30) == nullptr ); + CHECK( v.find(30) == nullptr ); } diff --git a/src/tests/vector.cpp b/src/tests/vector.cpp index 5c8866b..9ba9155 100644 --- a/src/tests/vector.cpp +++ b/src/tests/vector.cpp @@ -5,21 +5,21 @@ TEST_CASE( "sorted vector tests", "[containers] [vector]" ) { - using clock = std::chrono::system_clock; - unsigned seed = clock::now().time_since_epoch().count(); - std::default_random_engine rng(seed); - std::uniform_int_distribution distrib(0,10000); + using clock = std::chrono::system_clock; + unsigned seed = clock::now().time_since_epoch().count(); + std::default_random_engine rng(seed); + std::uniform_int_distribution distrib(0,10000); - kutil::vector v; + kutil::vector v; - int sizes[] = {1, 2, 3, 5, 100}; - for (int s : sizes) { - for (int i = 0; i < s; ++i) { - sortableT t { distrib(rng) }; - v.sorted_insert(t); - } + int sizes[] = {1, 2, 3, 5, 100}; + for (int s : sizes) { + for (int i = 0; i < s; ++i) { + sortableT t { distrib(rng) }; + v.sorted_insert(t); + } - for (int i = 1; i < s; ++i) - CHECK( v[i].value >= v[i-1].value ); - } + for (int i = 1; i < s; ++i) + CHECK( v[i].value >= v[i-1].value ); + } } diff --git a/src/user/drv.uefi_fb/font.cpp b/src/user/drv.uefi_fb/font.cpp index ee5b170..bb76992 100644 --- a/src/user/drv.uefi_fb/font.cpp +++ b/src/user/drv.uefi_fb/font.cpp @@ -15,17 +15,17 @@ const static uint8_t unicode_start = 0xfe; /* bits used in flags */ enum psf2_flags { - psf2_has_unicode = 0x00000001 + psf2_has_unicode = 0x00000001 }; struct psf2_header { - uint8_t magic[4]; - uint32_t version; - uint32_t header_size; // offset of bitmaps in file - uint32_t flags; - uint32_t length; // number of glyphs - uint32_t charsize; // number of bytes for each character - uint32_t height, width; // max dimensions of glyphs + uint8_t magic[4]; + uint32_t version; + uint32_t header_size; // offset of bitmaps in file + uint32_t flags; + uint32_t length; // number of glyphs + uint32_t charsize; // number of bytes for each character + uint32_t height, width; // max dimensions of glyphs }; const uint8_t default_font[] = { @@ -34,47 +34,47 @@ const uint8_t default_font[] = { }; font::font(void const *data) : - m_sizex {0}, - m_sizey {0}, - m_count {0}, - m_data {nullptr} + m_sizex {0}, + m_sizey {0}, + m_count {0}, + m_data {nullptr} { - if (!data) - data = default_font; + if (!data) + data = default_font; - psf2_header const *psf2 = static_cast(data); - for (int i = 0; i < sizeof(magic); ++i) { - assert(psf2->magic[i] == magic[i] && "Bad font magic number."); - } + psf2_header const *psf2 = static_cast(data); + for (int i = 0; i < sizeof(magic); ++i) { + assert(psf2->magic[i] == magic[i] && "Bad font magic number."); + } - m_data = static_cast(data) + psf2->header_size; - m_sizex = psf2->width; - m_sizey = psf2->height; - m_count = psf2->length; + m_data = static_cast(data) + psf2->header_size; + m_sizex = psf2->width; + m_sizey = psf2->height; + m_count = psf2->length; } void font::draw_glyph( - screen &s, - uint32_t glyph, - screen::pixel_t fg, - screen::pixel_t bg, - unsigned x, - unsigned y) const + screen &s, + uint32_t glyph, + screen::pixel_t fg, + screen::pixel_t bg, + unsigned x, + unsigned y) const { - unsigned bwidth = (m_sizex+7)/8; - uint8_t const *data = m_data + (glyph * glyph_bytes()); + unsigned bwidth = (m_sizex+7)/8; + uint8_t const *data = m_data + (glyph * glyph_bytes()); - for (int dy = 0; dy < m_sizey; ++dy) { - for (int dx = 0; dx < bwidth; ++dx) { - uint8_t byte = data[dy * bwidth + dx]; - for (int i = 0; i < 8; ++i) { - if (dx*8 + i >= m_sizex) break; - const uint8_t mask = 1 << (7-i); - uint32_t c = (byte & mask) ? fg : bg; - s.draw_pixel(x + dx*8 + i, y + dy, c); - } - } - } + for (int dy = 0; dy < m_sizey; ++dy) { + for (int dx = 0; dx < bwidth; ++dx) { + uint8_t byte = data[dy * bwidth + dx]; + for (int i = 0; i < 8; ++i) { + if (dx*8 + i >= m_sizex) break; + const uint8_t mask = 1 << (7-i); + uint32_t c = (byte & mask) ? fg : bg; + s.draw_pixel(x + dx*8 + i, y + dy, c); + } + } + } } diff --git a/src/user/drv.uefi_fb/font.h b/src/user/drv.uefi_fb/font.h index 3bf3bb8..1ad552b 100644 --- a/src/user/drv.uefi_fb/font.h +++ b/src/user/drv.uefi_fb/font.h @@ -6,28 +6,28 @@ class font { public: - /// Constructor. - /// \arg data The font data to load. If null, will load the default - /// built-in font. - font(void const *data = nullptr); + /// Constructor. + /// \arg data The font data to load. If null, will load the default + /// built-in font. + font(void const *data = nullptr); - unsigned glyph_bytes() const { return m_sizey * ((m_sizex + 7) / 8); } - unsigned count() const { return m_count; } - unsigned width() const { return m_sizex; } - unsigned height() const { return m_sizey; } - bool valid() const { return m_count > 0; } + unsigned glyph_bytes() const { return m_sizey * ((m_sizex + 7) / 8); } + unsigned count() const { return m_count; } + unsigned width() const { return m_sizex; } + unsigned height() const { return m_sizey; } + bool valid() const { return m_count > 0; } - void draw_glyph( - screen &s, - uint32_t glyph, - screen::pixel_t fg, - screen::pixel_t bg, - unsigned x, - unsigned y) const; + void draw_glyph( + screen &s, + uint32_t glyph, + screen::pixel_t fg, + screen::pixel_t bg, + unsigned x, + unsigned y) const; private: - unsigned m_sizex, m_sizey; - unsigned m_count; - uint8_t const *m_data; + unsigned m_sizex, m_sizey; + unsigned m_count; + uint8_t const *m_data; }; diff --git a/src/user/drv.uefi_fb/main.cpp b/src/user/drv.uefi_fb/main.cpp index 196b90f..387247b 100644 --- a/src/user/drv.uefi_fb/main.cpp +++ b/src/user/drv.uefi_fb/main.cpp @@ -14,8 +14,8 @@ #include "scrollback.h" extern "C" { - int main(int, const char **); - void _get_init(size_t *initc, struct j6_init_value **initv); + int main(int, const char **); + void _get_init(size_t *initc, struct j6_init_value **initv); } extern j6_handle_t __handle_sys; @@ -23,118 +23,118 @@ extern j6_handle_t __handle_self; struct entry { - uint8_t bytes; - uint8_t area; - uint8_t severity; - uint8_t sequence; - char message[0]; + uint8_t bytes; + uint8_t area; + uint8_t severity; + uint8_t sequence; + char message[0]; }; int main(int argc, const char **argv) { - j6_system_log("fb driver starting"); + j6_system_log("fb driver starting"); - size_t initc = 0; - j6_init_value *initv = nullptr; - _get_init(&initc, &initv); + size_t initc = 0; + j6_init_value *initv = nullptr; + _get_init(&initc, &initv); - j6_init_framebuffer *fb = nullptr; - for (unsigned i = 0; i < initc; ++i) { - if (initv[i].type == j6_init_desc_framebuffer) { - fb = reinterpret_cast(initv[i].data); - break; - } - } + j6_init_framebuffer *fb = nullptr; + for (unsigned i = 0; i < initc; ++i) { + if (initv[i].type == j6_init_desc_framebuffer) { + fb = reinterpret_cast(initv[i].data); + break; + } + } - if (!fb || fb->addr == 0) { - j6_system_log("fb driver didn't find a framebuffer, exiting"); - return 1; - } + if (!fb || fb->addr == 0) { + j6_system_log("fb driver didn't find a framebuffer, exiting"); + return 1; + } - j6_handle_t fb_handle = j6_handle_invalid; - uint32_t flags = - j6_vm_flag_write | - j6_vm_flag_write_combine | - j6_vm_flag_mmio; - j6_status_t s = j6_system_map_phys(__handle_sys, &fb_handle, fb->addr, fb->size, flags); - if (s != j6_status_ok) { - return s; - } + j6_handle_t fb_handle = j6_handle_invalid; + uint32_t flags = + j6_vm_flag_write | + j6_vm_flag_write_combine | + j6_vm_flag_mmio; + j6_status_t s = j6_system_map_phys(__handle_sys, &fb_handle, fb->addr, fb->size, flags); + if (s != j6_status_ok) { + return s; + } - s = j6_vma_map(fb_handle, __handle_self, fb->addr); - if (s != j6_status_ok) { - return s; - } + s = j6_vma_map(fb_handle, __handle_self, fb->addr); + if (s != j6_status_ok) { + return s; + } - const screen::pixel_order order = (fb->flags & 1) ? - screen::pixel_order::bgr8 : screen::pixel_order::rgb8; + const screen::pixel_order order = (fb->flags & 1) ? + screen::pixel_order::bgr8 : screen::pixel_order::rgb8; - screen scr( - reinterpret_cast(fb->addr), - fb->horizontal, - fb->vertical, - fb->scanline, - order); + screen scr( + reinterpret_cast(fb->addr), + fb->horizontal, + fb->vertical, + fb->scanline, + order); - font fnt; + font fnt; - screen::pixel_t fg = scr.color(0xb0, 0xb0, 0xb0); - screen::pixel_t bg = scr.color(49, 79, 128); - scr.fill(bg); - scr.update(); + screen::pixel_t fg = scr.color(0xb0, 0xb0, 0xb0); + screen::pixel_t bg = scr.color(49, 79, 128); + scr.fill(bg); + scr.update(); - constexpr int margin = 2; - const unsigned xstride = (margin + fnt.width()); - const unsigned ystride = (margin + fnt.height()); - const unsigned rows = (scr.height() - margin) / ystride; - const unsigned cols = (scr.width() - margin) / xstride; + constexpr int margin = 2; + const unsigned xstride = (margin + fnt.width()); + const unsigned ystride = (margin + fnt.height()); + const unsigned rows = (scr.height() - margin) / ystride; + const unsigned cols = (scr.width() - margin) / xstride; - scrollback scroll(rows, cols); + scrollback scroll(rows, cols); - int pending = 0; - constexpr int pending_threshold = 5; + int pending = 0; + constexpr int pending_threshold = 5; - j6_handle_t sys = __handle_sys; - size_t buffer_size = 0; - void *message_buffer = nullptr; + j6_handle_t sys = __handle_sys; + size_t buffer_size = 0; + void *message_buffer = nullptr; - while (true) { - size_t size = buffer_size; - j6_status_t s = j6_system_get_log(sys, message_buffer, &size); + while (true) { + size_t size = buffer_size; + j6_status_t s = j6_system_get_log(sys, message_buffer, &size); - if (s == j6_err_insufficient) { - free(message_buffer); - message_buffer = malloc(size * 2); - buffer_size = size; - continue; - } else if (s != j6_status_ok) { - j6_system_log("fb driver got error from get_log, quitting"); - return s; - } + if (s == j6_err_insufficient) { + free(message_buffer); + message_buffer = malloc(size * 2); + buffer_size = size; + continue; + } else if (s != j6_status_ok) { + j6_system_log("fb driver got error from get_log, quitting"); + return s; + } - if (size > 0) { - entry *e = reinterpret_cast(message_buffer); + if (size > 0) { + entry *e = reinterpret_cast(message_buffer); - size_t eom = e->bytes - sizeof(entry); - e->message[eom] = 0; + size_t eom = e->bytes - sizeof(entry); + e->message[eom] = 0; - scroll.add_line(e->message, eom); - if (++pending > pending_threshold) { - scroll.render(scr, fnt); - scr.update(); - pending = 0; - } - } else { - if (pending) { - scroll.render(scr, fnt); - scr.update(); - pending = 0; - } - } - } + scroll.add_line(e->message, eom); + if (++pending > pending_threshold) { + scroll.render(scr, fnt); + scr.update(); + pending = 0; + } + } else { + if (pending) { + scroll.render(scr, fnt); + scr.update(); + pending = 0; + } + } + } - j6_system_log("fb driver done, exiting"); - return 0; + j6_system_log("fb driver done, exiting"); + return 0; } diff --git a/src/user/drv.uefi_fb/screen.cpp b/src/user/drv.uefi_fb/screen.cpp index 872e9ec..7a82a81 100644 --- a/src/user/drv.uefi_fb/screen.cpp +++ b/src/user/drv.uefi_fb/screen.cpp @@ -3,46 +3,46 @@ #include "screen.h" screen::screen(volatile void *addr, unsigned hres, unsigned vres, unsigned scanline, pixel_order order) : - m_fb(static_cast(addr)), - m_order(order), - m_scanline(scanline), - m_resx(hres), - m_resy(vres) + m_fb(static_cast(addr)), + m_order(order), + m_scanline(scanline), + m_resx(hres), + m_resy(vres) { - const size_t size = scanline * vres; - m_back = reinterpret_cast(malloc(size * sizeof(pixel_t))); + const size_t size = scanline * vres; + m_back = reinterpret_cast(malloc(size * sizeof(pixel_t))); } screen::pixel_t screen::color(uint8_t r, uint8_t g, uint8_t b) const { - switch (m_order) { - case pixel_order::bgr8: - return - (static_cast(b) << 0) | - (static_cast(g) << 8) | - (static_cast(r) << 16); + switch (m_order) { + case pixel_order::bgr8: + return + (static_cast(b) << 0) | + (static_cast(g) << 8) | + (static_cast(r) << 16); - case pixel_order::rgb8: - return - (static_cast(r) << 0) | - (static_cast(g) << 8) | - (static_cast(b) << 16); - } + case pixel_order::rgb8: + return + (static_cast(r) << 0) | + (static_cast(g) << 8) | + (static_cast(b) << 16); + } } void screen::fill(pixel_t color) { - const size_t len = m_scanline * m_resy; - asm volatile ( "rep stosl" : : - "a"(color), "c"(len), "D"(m_back) ); + const size_t len = m_scanline * m_resy; + asm volatile ( "rep stosl" : : + "a"(color), "c"(len), "D"(m_back) ); } void screen::update() { - const size_t len = m_scanline * m_resy * sizeof(pixel_t); - asm volatile ( "rep movsb" : : - "c"(len), "S"(m_back), "D"(m_fb) ); + const size_t len = m_scanline * m_resy * sizeof(pixel_t); + asm volatile ( "rep movsb" : : + "c"(len), "S"(m_back), "D"(m_fb) ); } diff --git a/src/user/drv.uefi_fb/screen.h b/src/user/drv.uefi_fb/screen.h index b55903b..4bf6a75 100644 --- a/src/user/drv.uefi_fb/screen.h +++ b/src/user/drv.uefi_fb/screen.h @@ -5,32 +5,32 @@ class screen { public: - using pixel_t = uint32_t; + using pixel_t = uint32_t; - enum class pixel_order : uint8_t { bgr8, rgb8, }; + enum class pixel_order : uint8_t { bgr8, rgb8, }; - screen(volatile void *addr, unsigned hres, unsigned vres, unsigned scanline, pixel_order order); + screen(volatile void *addr, unsigned hres, unsigned vres, unsigned scanline, pixel_order order); - unsigned width() const { return m_resx; } - unsigned height() const { return m_resy; } + unsigned width() const { return m_resx; } + unsigned height() const { return m_resy; } - pixel_t color(uint8_t r, uint8_t g, uint8_t b) const; + pixel_t color(uint8_t r, uint8_t g, uint8_t b) const; - void fill(pixel_t color); + void fill(pixel_t color); - inline void draw_pixel(unsigned x, unsigned y, pixel_t color) { - const size_t index = x + y * m_scanline; - m_back[index] = color; - } + inline void draw_pixel(unsigned x, unsigned y, pixel_t color) { + const size_t index = x + y * m_scanline; + m_back[index] = color; + } - void update(); + void update(); private: - volatile pixel_t *m_fb; - pixel_t *m_back; - pixel_order m_order; - unsigned m_scanline; - unsigned m_resx, m_resy; + volatile pixel_t *m_fb; + pixel_t *m_back; + pixel_order m_order; + unsigned m_scanline; + unsigned m_resx, m_resy; - screen() = delete; + screen() = delete; }; diff --git a/src/user/drv.uefi_fb/scrollback.cpp b/src/user/drv.uefi_fb/scrollback.cpp index 50c28f6..955ea35 100644 --- a/src/user/drv.uefi_fb/scrollback.cpp +++ b/src/user/drv.uefi_fb/scrollback.cpp @@ -6,53 +6,53 @@ #include "scrollback.h" scrollback::scrollback(unsigned lines, unsigned cols, unsigned margin) : - m_rows {lines}, - m_cols {cols}, - m_count {0}, - m_margin {margin} + m_rows {lines}, + m_cols {cols}, + m_count {0}, + m_margin {margin} { - m_data = reinterpret_cast(malloc(lines*cols)); - memset(m_data, ' ', lines*cols); + m_data = reinterpret_cast(malloc(lines*cols)); + memset(m_data, ' ', lines*cols); } void scrollback::add_line(const char *line, size_t len) { - unsigned i = m_count++ % m_rows; + unsigned i = m_count++ % m_rows; - if (len > m_cols) - len = m_cols; + if (len > m_cols) + len = m_cols; - char *start = m_data + (i * m_cols); - memcpy(start, line, len); - if (len < m_cols) - memset(start + len, ' ', m_cols - len); + char *start = m_data + (i * m_cols); + memcpy(start, line, len); + if (len < m_cols) + memset(start + len, ' ', m_cols - len); } char * scrollback::get_line(unsigned i) { - unsigned line = (i + m_count) % m_rows; - return &m_data[line*m_cols]; + unsigned line = (i + m_count) % m_rows; + return &m_data[line*m_cols]; } void scrollback::render(screen &scr, font &fnt) { - screen::pixel_t fg = scr.color(0xb0, 0xb0, 0xb0); - screen::pixel_t bg = scr.color(49, 79, 128); + screen::pixel_t fg = scr.color(0xb0, 0xb0, 0xb0); + screen::pixel_t bg = scr.color(49, 79, 128); - const unsigned xstride = (m_margin + fnt.width()); - const unsigned ystride = (m_margin + fnt.height()); + const unsigned xstride = (m_margin + fnt.width()); + const unsigned ystride = (m_margin + fnt.height()); - unsigned start = m_count <= m_rows ? 0 : - m_count % m_rows; + unsigned start = m_count <= m_rows ? 0 : + m_count % m_rows; - for (unsigned y = 0; y < m_rows; ++y) { - unsigned i = (start + y) % m_rows; - char *line = &m_data[i*m_cols]; - for (unsigned x = 0; x < m_cols; ++x) { - fnt.draw_glyph(scr, line[x], fg, bg, m_margin+x*xstride, m_margin+y*ystride); - } - } + for (unsigned y = 0; y < m_rows; ++y) { + unsigned i = (start + y) % m_rows; + char *line = &m_data[i*m_cols]; + for (unsigned x = 0; x < m_cols; ++x) { + fnt.draw_glyph(scr, line[x], fg, bg, m_margin+x*xstride, m_margin+y*ystride); + } + } } diff --git a/src/user/drv.uefi_fb/scrollback.h b/src/user/drv.uefi_fb/scrollback.h index 9d97546..13442c6 100644 --- a/src/user/drv.uefi_fb/scrollback.h +++ b/src/user/drv.uefi_fb/scrollback.h @@ -7,19 +7,19 @@ class font; class scrollback { public: - scrollback(unsigned lines, unsigned cols, unsigned margin = 2); + scrollback(unsigned lines, unsigned cols, unsigned margin = 2); - void add_line(const char *line, size_t len); + void add_line(const char *line, size_t len); - char * get_line(unsigned i); + char * get_line(unsigned i); - void render(screen &scr, font &fnt); + void render(screen &scr, font &fnt); private: - char *m_data; - unsigned m_rows, m_cols; - unsigned m_start; - unsigned m_count; - unsigned m_margin; + char *m_data; + unsigned m_rows, m_cols; + unsigned m_start; + unsigned m_count; + unsigned m_margin; }; diff --git a/src/user/srv.init/main.cpp b/src/user/srv.init/main.cpp index ece29a0..b8bcd95 100644 --- a/src/user/srv.init/main.cpp +++ b/src/user/srv.init/main.cpp @@ -2,7 +2,7 @@ #include "modules.h" extern "C" { - int main(int, const char **); + int main(int, const char **); } uintptr_t _arg_modules_phys; // This gets filled in in _start @@ -13,8 +13,8 @@ j6_handle_t handle_system = 2; // boot protocol is that init gets the system as int main(int argc, const char **argv) { - j6_system_log("srv.init starting"); - modules::load_all(_arg_modules_phys); + j6_system_log("srv.init starting"); + modules::load_all(_arg_modules_phys); - return 0; + return 0; } diff --git a/src/user/srv.init/modules.cpp b/src/user/srv.init/modules.cpp index a61bdfb..17fe372 100644 --- a/src/user/srv.init/modules.cpp +++ b/src/user/srv.init/modules.cpp @@ -18,53 +18,53 @@ namespace modules { static const modules_page * load_page(uintptr_t address) { - j6_handle_t mods_vma = j6_handle_invalid; - j6_status_t s = j6_system_map_phys(handle_system, &mods_vma, address, 0x1000, 0); - if (s != j6_status_ok) - exit(s); + j6_handle_t mods_vma = j6_handle_invalid; + j6_status_t s = j6_system_map_phys(handle_system, &mods_vma, address, 0x1000, 0); + if (s != j6_status_ok) + exit(s); - s = j6_vma_map(mods_vma, handle_self, address); - if (s != j6_status_ok) - exit(s); + s = j6_vma_map(mods_vma, handle_self, address); + if (s != j6_status_ok) + exit(s); - return reinterpret_cast(address); + return reinterpret_cast(address); } void load_all(uintptr_t address) { - module_framebuffer const *framebuffer = nullptr; + module_framebuffer const *framebuffer = nullptr; - while (address) { - const modules_page *page = load_page(address); + while (address) { + const modules_page *page = load_page(address); - char message[100]; - sprintf(message, "srv.init loading %d modules from page at 0x%lx", page->count, address); - j6_system_log(message); + char message[100]; + sprintf(message, "srv.init loading %d modules from page at 0x%lx", page->count, address); + j6_system_log(message); - module *mod = page->modules; - size_t count = page->count; - while (count--) { - switch (mod->mod_type) { - case module_type::framebuffer: - framebuffer = reinterpret_cast(mod); - break; + module *mod = page->modules; + size_t count = page->count; + while (count--) { + switch (mod->mod_type) { + case module_type::framebuffer: + framebuffer = reinterpret_cast(mod); + break; - case module_type::program: - if (mod->mod_flags == module_flags::no_load) - j6_system_log("Loaded program module"); - else - j6_system_log("Non-loaded program module"); - break; + case module_type::program: + if (mod->mod_flags == module_flags::no_load) + j6_system_log("Loaded program module"); + else + j6_system_log("Non-loaded program module"); + break; - default: - j6_system_log("Unknown module"); - } - mod = offset_ptr(mod, mod->mod_length); - } + default: + j6_system_log("Unknown module"); + } + mod = offset_ptr(mod, mod->mod_length); + } - address = page->next; - } + address = page->next; + } } } // namespace modules diff --git a/src/user/testapp/io.cpp b/src/user/testapp/io.cpp index c9ed88f..f5aa618 100644 --- a/src/user/testapp/io.cpp +++ b/src/user/testapp/io.cpp @@ -3,20 +3,20 @@ uint8_t inb(uint16_t port) { - uint8_t val; - __asm__ __volatile__ ( "inb %1, %0" : "=a"(val) : "Nd"(port) ); - return val; + uint8_t val; + __asm__ __volatile__ ( "inb %1, %0" : "=a"(val) : "Nd"(port) ); + return val; } void outb(uint16_t port, uint8_t val) { - __asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) ); + __asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) ); } void io_wait(unsigned times) { - for (unsigned i = 0; i < times; ++i) - outb(0x80, 0); + for (unsigned i = 0; i < times; ++i) + outb(0x80, 0); } diff --git a/src/user/testapp/main.cpp b/src/user/testapp/main.cpp index e8edfef..d77d64b 100644 --- a/src/user/testapp/main.cpp +++ b/src/user/testapp/main.cpp @@ -14,139 +14,139 @@ extern j6_handle_t __handle_sys; j6_handle_t endp = j6_handle_invalid; extern "C" { - int main(int, const char **); + int main(int, const char **); } void thread_proc() { - j6_system_log("sub thread starting"); + j6_system_log("sub thread starting"); - char buffer[512]; - size_t len = sizeof(buffer); - j6_tag_t tag = 0; - j6_status_t result = j6_endpoint_receive(endp, &tag, &len, (void*)buffer); - if (result != j6_status_ok) - j6_thread_exit(result); + char buffer[512]; + size_t len = sizeof(buffer); + j6_tag_t tag = 0; + j6_status_t result = j6_endpoint_receive(endp, &tag, &len, (void*)buffer); + if (result != j6_status_ok) + j6_thread_exit(result); - j6_system_log("sub thread received message"); + j6_system_log("sub thread received message"); - for (int i = 0; i < len; ++i) - if (buffer[i] >= 'A' && buffer[i] <= 'Z') - buffer[i] += 0x20; + for (int i = 0; i < len; ++i) + if (buffer[i] >= 'A' && buffer[i] <= 'Z') + buffer[i] += 0x20; - tag++; - result = j6_endpoint_send(endp, tag, len, (void*)buffer); - if (result != j6_status_ok) - j6_thread_exit(result); + tag++; + result = j6_endpoint_send(endp, tag, len, (void*)buffer); + if (result != j6_status_ok) + j6_thread_exit(result); - j6_system_log("sub thread sent message"); + j6_system_log("sub thread sent message"); - for (int i = 1; i < 5; ++i) - j6_thread_sleep(i*10); + for (int i = 1; i < 5; ++i) + j6_thread_sleep(i*10); - j6_system_log("sub thread exiting"); - j6_thread_exit(0); + j6_system_log("sub thread exiting"); + j6_thread_exit(0); } int main(int argc, const char **argv) { - j6_handle_t children[2] = {j6_handle_invalid, j6_handle_invalid}; - j6_signal_t out = 0; + j6_handle_t children[2] = {j6_handle_invalid, j6_handle_invalid}; + j6_signal_t out = 0; - j6_system_log("main thread starting"); + j6_system_log("main thread starting"); - for (int i = 0; i < argc; ++i) - j6_system_log(argv[i]); + for (int i = 0; i < argc; ++i) + j6_system_log(argv[i]); - void *base = malloc(0x1000); - if (!base) - return 1; + void *base = malloc(0x1000); + if (!base) + return 1; - uint64_t *vma_ptr = reinterpret_cast(base); - for (int i = 0; i < 3; ++i) - vma_ptr[i*100] = uint64_t(i); + uint64_t *vma_ptr = reinterpret_cast(base); + for (int i = 0; i < 3; ++i) + vma_ptr[i*100] = uint64_t(i); - j6_system_log("main thread wrote to memory area"); + j6_system_log("main thread wrote to memory area"); - j6_status_t result = j6_endpoint_create(&endp); - if (result != j6_status_ok) - return result; + j6_status_t result = j6_endpoint_create(&endp); + if (result != j6_status_ok) + return result; - j6_system_log("main thread created endpoint"); + j6_system_log("main thread created endpoint"); - result = j6_thread_create(reinterpret_cast(&thread_proc), &children[1]); - if (result != j6_status_ok) - return result; + result = j6_thread_create(reinterpret_cast(&thread_proc), &children[1]); + if (result != j6_status_ok) + return result; - j6_system_log("main thread created sub thread"); + j6_system_log("main thread created sub thread"); - char message[] = "MAIN THREAD SUCCESSFULLY CALLED SENDRECV IF THIS IS LOWERCASE"; - size_t size = sizeof(message); - j6_tag_t tag = 16; - result = j6_endpoint_sendrecv(endp, &tag, &size, (void*)message); - if (result != j6_status_ok) - return result; + char message[] = "MAIN THREAD SUCCESSFULLY CALLED SENDRECV IF THIS IS LOWERCASE"; + size_t size = sizeof(message); + j6_tag_t tag = 16; + result = j6_endpoint_sendrecv(endp, &tag, &size, (void*)message); + if (result != j6_status_ok) + return result; - if (tag != 17) - j6_system_log("GOT WRONG TAG FROM SENDRECV"); + if (tag != 17) + j6_system_log("GOT WRONG TAG FROM SENDRECV"); - result = j6_system_bind_irq(__handle_sys, endp, 3); - if (result != j6_status_ok) - return result; + result = j6_system_bind_irq(__handle_sys, endp, 3); + if (result != j6_status_ok) + return result; - j6_system_log(message); + j6_system_log(message); - j6_system_log("main thread creating a new process"); - result = j6_process_create(&children[0]); - if (result != j6_status_ok) - return result; + j6_system_log("main thread creating a new process"); + result = j6_process_create(&children[0]); + if (result != j6_status_ok) + return result; - j6_system_log("main thread waiting on children"); + j6_system_log("main thread waiting on children"); - j6_handle_t outhandle; - result = j6_object_wait_many(children, 2, -1ull, &outhandle, &out); - if (result != j6_status_ok) - return result; + j6_handle_t outhandle; + result = j6_object_wait_many(children, 2, -1ull, &outhandle, &out); + if (result != j6_status_ok) + return result; - if (outhandle == children[1]) { - j6_system_log(" ok from child thread"); - } else if (outhandle == children[0]) { - j6_system_log(" ok from child process"); - } else { - j6_system_log(" ... got unknown handle"); - } + if (outhandle == children[1]) { + j6_system_log(" ok from child thread"); + } else if (outhandle == children[0]) { + j6_system_log(" ok from child process"); + } else { + j6_system_log(" ... got unknown handle"); + } - j6_system_log("main testing irqs"); + j6_system_log("main testing irqs"); - serial_port com2(COM2); + serial_port com2(COM2); - const char *fgseq = "\x1b[2J"; - while (*fgseq) - com2.write(*fgseq++); + const char *fgseq = "\x1b[2J"; + while (*fgseq) + com2.write(*fgseq++); - for (int i = 0; i < 10; ++i) - com2.write('%'); + for (int i = 0; i < 10; ++i) + com2.write('%'); - size_t len = 0; - while (true) { - result = j6_endpoint_receive(endp, &tag, &len, nullptr); - if (result != j6_status_ok) - return result; + size_t len = 0; + while (true) { + result = j6_endpoint_receive(endp, &tag, &len, nullptr); + if (result != j6_status_ok) + return result; - if (j6_tag_is_irq(tag)) - j6_system_log("main thread got irq!"); - } + if (j6_tag_is_irq(tag)) + j6_system_log("main thread got irq!"); + } - j6_system_log("main thread closing endpoint"); + j6_system_log("main thread closing endpoint"); - result = j6_object_close(endp); - if (result != j6_status_ok) - return result; + result = j6_object_close(endp); + if (result != j6_status_ok) + return result; - j6_system_log("main thread done, exiting"); - return 0; + j6_system_log("main thread done, exiting"); + return 0; } diff --git a/src/user/testapp/serial.cpp b/src/user/testapp/serial.cpp index bda4979..f8de54b 100644 --- a/src/user/testapp/serial.cpp +++ b/src/user/testapp/serial.cpp @@ -3,39 +3,39 @@ serial_port::serial_port() : - m_port(0) + m_port(0) { } serial_port::serial_port(uint16_t port) : - m_port(port) + m_port(port) { - outb(port + 1, 0x00); // Disable all interrupts - outb(port + 3, 0x80); // Enable the Divisor Latch Access Bit - outb(port + 0, 0x01); // Divisor low bit: 1 (115200 baud) - outb(port + 1, 0x00); // Divisor high bit - outb(port + 3, 0x03); // 8-N-1 - outb(port + 2, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger - outb(port + 4, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable) - outb(port + 1, 0x03); // Enable interrupts + outb(port + 1, 0x00); // Disable all interrupts + outb(port + 3, 0x80); // Enable the Divisor Latch Access Bit + outb(port + 0, 0x01); // Divisor low bit: 1 (115200 baud) + outb(port + 1, 0x00); // Divisor high bit + outb(port + 3, 0x03); // 8-N-1 + outb(port + 2, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger + outb(port + 4, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable) + outb(port + 1, 0x03); // Enable interrupts } bool serial_port::read_ready() { return (inb(m_port + 5) & 0x01) != 0; } bool serial_port::write_ready() { - uint8_t lsr = inb(m_port + 5); - return (lsr & 0x20) != 0; + uint8_t lsr = inb(m_port + 5); + return (lsr & 0x20) != 0; } char serial_port::read() { - while (!read_ready()); - return inb(m_port); + while (!read_ready()); + return inb(m_port); } void serial_port::write(char c) { - while (!write_ready()); - outb(m_port, c); + while (!write_ready()); + outb(m_port, c); } diff --git a/src/user/testapp/serial.h b/src/user/testapp/serial.h index 4d895cd..4bc7a16 100644 --- a/src/user/testapp/serial.h +++ b/src/user/testapp/serial.h @@ -8,19 +8,19 @@ class serial_port { public: - /// Constructor. - /// \arg port The IO address of the serial port - serial_port(uint16_t port); + /// Constructor. + /// \arg port The IO address of the serial port + serial_port(uint16_t port); - serial_port(); + serial_port(); - void write(char c); - char read(); + void write(char c); + char read(); private: - uint16_t m_port; + uint16_t m_port; - bool read_ready(); - bool write_ready(); + bool read_ready(); + bool write_ready(); };