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