diff --git a/configure b/configure index 4ba5ff9..0894710 100755 --- a/configure +++ b/configure @@ -25,7 +25,12 @@ def generate(output, config, manifest): modules[m.name] = m return m - glo = {'module': module_init} + glo = { + "module": module_init, + "source_root": root, + "built_root": output, + "module_root": path, + } code = compile(open(fullpath, 'r').read(), fullpath, "exec") loc = {} diff --git a/definitions/memory_layout.csv b/definitions/memory_layout.csv new file mode 100644 index 0000000..9ec2f54 --- /dev/null +++ b/definitions/memory_layout.csv @@ -0,0 +1,5 @@ +linear,64T,shared +bitmap,1T,shared +heap,64G +stacks,64G +buffers,64G diff --git a/scripts/bonnibel/module.py b/scripts/bonnibel/module.py index d659511..cfc4a14 100644 --- a/scripts/bonnibel/module.py +++ b/scripts/bonnibel/module.py @@ -187,3 +187,8 @@ class Module: s = Source(self.root, path, **kwargs) self.sources.append(s) return str(s.output) + + def add_depends(self, paths, deps): + for source in self.sources: + if source.name in paths: + source.add_deps(deps) diff --git a/scripts/bonnibel/source.py b/scripts/bonnibel/source.py index be4dc44..41a0e64 100644 --- a/scripts/bonnibel/source.py +++ b/scripts/bonnibel/source.py @@ -53,11 +53,14 @@ class Source: self.__root = Path(root) self.__path = Path(path) self.__output = output - self.__deps = deps + self.__deps = tuple(deps) def __str__(self): return self.input + def add_deps(self, deps): + self.__deps += tuple(deps) + @property def action(self): suffix = self.__path.suffix diff --git a/scripts/memory.py b/scripts/memory.py new file mode 100644 index 0000000..47bf959 --- /dev/null +++ b/scripts/memory.py @@ -0,0 +1,30 @@ +class Layout: + from collections import namedtuple + Region = namedtuple("Region", ("name", "start", "size", "shared")) + + sizes = {'G': 1024 ** 3, 'T': 1024 ** 4} + + def __init__(self, path): + import csv + + regions = [] + addr = 1 << 64 + + with open(path, newline='') as infile: + reader = csv.reader(infile) + for row in reader: + name, size = row[:2] + shared = (len(row) > 2 and "shared" in row[2]) + + size, mag = int(size[:-1]), size[-1] + + try: + mult = Layout.sizes[mag] + except KeyError: + raise RuntimeError(f"No magnitude named '{mag}'.") + + size *= mult + addr -= size + regions.append(Layout.Region(name, addr, size, shared)) + + self.regions = tuple(regions) diff --git a/src/boot/allocator.cpp b/src/boot/allocator.cpp index c4cb878..9f777a7 100644 --- a/src/boot/allocator.cpp +++ b/src/boot/allocator.cpp @@ -1,11 +1,13 @@ #include #include + +#include +#include #include +#include #include "allocator.h" #include "error.h" -#include "init_args.h" -#include "kernel_args.h" #include "memory.h" namespace boot { @@ -15,9 +17,9 @@ memory::allocator &g_alloc = __g_alloc_storage.value; namespace memory { -using kernel::init::allocation_register; -using kernel::init::module; -using kernel::init::page_allocation; +using bootproto::allocation_register; +using bootproto::module; +using bootproto::page_allocation; static_assert(sizeof(allocation_register) == page_size); @@ -119,7 +121,7 @@ allocator::allocate_module_untyped(size_t size) ++m_modules->count; module *m = m_next_mod; - m_next_mod = offset_ptr(m_next_mod, size); + m_next_mod = util::offset_pointer(m_next_mod, size); m->mod_length = size; return m; diff --git a/src/boot/allocator.h b/src/boot/allocator.h index 45c9fc2..822f0e7 100644 --- a/src/boot/allocator.h +++ b/src/boot/allocator.h @@ -6,25 +6,24 @@ namespace uefi { class boot_services; } -namespace kernel { -namespace init { +namespace bootproto { enum class allocation_type : uint8_t; struct allocation_register; struct module; struct modules_page; -}} +} namespace boot { namespace memory { -using alloc_type = kernel::init::allocation_type; +using alloc_type = bootproto::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 = bootproto::allocation_register; + using module = bootproto::module; + using modules_page = bootproto::modules_page; allocator(uefi::boot_services &bs); diff --git a/src/boot/boot.module b/src/boot/boot.module index 13b71da..bb13011 100644 --- a/src/boot/boot.module +++ b/src/boot/boot.module @@ -4,7 +4,7 @@ module("boot", kind = "exe", output = "boot.efi", targets = [ "boot" ], - deps = [ "cpu", "elf", "util" ], + deps = [ "cpu", "elf", "util", "bootproto" ], sources = [ "allocator.cpp", "console.cpp", diff --git a/src/boot/error.cpp b/src/boot/error.cpp index 68fccb1..31cffc2 100644 --- a/src/boot/error.cpp +++ b/src/boot/error.cpp @@ -1,6 +1,5 @@ #include "error.h" #include "console.h" -#include "kernel_args.h" #include "status.h" namespace boot { diff --git a/src/boot/fs.cpp b/src/boot/fs.cpp index a3146b2..9dd7917 100644 --- a/src/boot/fs.cpp +++ b/src/boot/fs.cpp @@ -5,11 +5,12 @@ #include #include +#include + #include "allocator.h" #include "console.h" #include "error.h" #include "fs.h" -#include "kernel_args.h" #include "memory.h" #include "status.h" @@ -53,7 +54,7 @@ file::open(const wchar_t *path) return file(fh); } -buffer +util::buffer file::load() { uint8_t info_buf[sizeof(uefi::protos::file_info) + 100]; diff --git a/src/boot/fs.h b/src/boot/fs.h index f183b94..c2b828a 100644 --- a/src/boot/fs.h +++ b/src/boot/fs.h @@ -3,7 +3,7 @@ #pragma once #include -#include "counted.h" +#include namespace uefi { struct boot_services; @@ -29,7 +29,7 @@ public: /// Load the contents of this file into memory. /// \returns A buffer describing the loaded memory. The /// memory will be page-aligned. - buffer load(); + util::buffer load(); private: friend file get_boot_volume(uefi::handle, uefi::boot_services*); diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index 7a5df50..0ae36b2 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -1,27 +1,26 @@ #include #include +#include +#include +#include +#include + #include "allocator.h" #include "console.h" -#include "elf/file.h" -#include "elf/headers.h" #include "error.h" #include "fs.h" -#include "init_args.h" #include "loader.h" #include "memory.h" #include "paging.h" -#include "pointer_manipulation.h" #include "status.h" -namespace init = kernel::init; - namespace boot { namespace loader { using memory::alloc_type; -buffer +util::buffer load_file( fs::file &disk, const program_desc &desc) @@ -29,7 +28,7 @@ load_file( status_line status(L"Loading file", desc.path); fs::file file = disk.open(desc.path); - buffer b = file.load(); + util::buffer b = file.load(); //console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size); return b; @@ -37,17 +36,17 @@ load_file( static void -create_module(buffer data, const program_desc &desc, bool loaded) +create_module(util::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; + bootproto::module_program *mod = g_alloc.allocate_module(path_len); + mod->mod_type = bootproto::module_type::program; mod->base_address = reinterpret_cast(data.pointer); mod->size = data.count; if (loaded) - mod->mod_flags = static_cast( + mod->mod_flags = static_cast( static_cast(mod->mod_flags) | - static_cast(init::module_flags::no_load)); + static_cast(bootproto::module_flags::no_load)); // TODO: support non-ascii path characters and do real utf-16 to utf-8 // conversion @@ -56,7 +55,7 @@ create_module(buffer data, const program_desc &desc, bool loaded) mod->filename[path_len] = 0; } -init::program * +bootproto::program * load_program( fs::file &disk, const program_desc &desc, @@ -64,7 +63,7 @@ load_program( { status_line status(L"Loading program", desc.name); - buffer data = load_file(disk, desc); + util::buffer data = load_file(disk, desc); if (add_module) create_module(data, desc, true); @@ -79,20 +78,20 @@ load_program( ++num_sections; } - init::program_section *sections = new init::program_section [num_sections]; + bootproto::program_section *sections = new bootproto::program_section [num_sections]; 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++]; + bootproto::program_section §ion = sections[next_section++]; 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); + void *source = util::offset_pointer(data.pointer, seg.offset); g_alloc.copy(pages, source, seg.file_size); section.phys_addr = reinterpret_cast(pages); } else { @@ -101,10 +100,10 @@ load_program( section.virt_addr = seg.vaddr; section.size = seg.mem_size; - section.type = static_cast(seg.flags); + section.type = static_cast(seg.flags); } - init::program *prog = new init::program; + bootproto::program *prog = new bootproto::program; prog->sections = { .pointer = sections, .count = num_sections }; prog->phys_base = program.base(); prog->entrypoint = program.entrypoint(); @@ -118,25 +117,25 @@ load_module( { status_line status(L"Loading module", desc.name); - buffer data = load_file(disk, desc); + util::buffer data = load_file(disk, desc); create_module(data, desc, false); } void -verify_kernel_header(init::program &program) +verify_kernel_header(bootproto::program &program) { status_line status(L"Verifying kernel header"); - const init::header *header = - reinterpret_cast(program.sections[0].phys_addr); + const bootproto::header *header = + reinterpret_cast(program.sections[0].phys_addr); - if (header->magic != init::header_magic) + if (header->magic != bootproto::header_magic) error::raise(uefi::status::load_error, L"Bad kernel magic number"); - if (header->length < sizeof(init::header)) + if (header->length < sizeof(bootproto::header)) error::raise(uefi::status::load_error, L"Bad kernel header length"); - if (header->version < init::min_header_version) + if (header->version < bootproto::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", diff --git a/src/boot/loader.h b/src/boot/loader.h index 0baeaba..3fc2966 100644 --- a/src/boot/loader.h +++ b/src/boot/loader.h @@ -2,13 +2,12 @@ /// Definitions for loading the kernel into memory #pragma once -#include "counted.h" +#include -namespace kernel { -namespace init { +namespace bootproto { struct program; struct module; -}} +} namespace boot { @@ -27,7 +26,7 @@ struct program_desc /// Load a file from disk into memory. /// \arg disk The opened UEFI filesystem to load from /// \arg desc The program descriptor identifying the file -buffer +util::buffer load_file( fs::file &disk, const program_desc &desc); @@ -36,7 +35,7 @@ load_file( /// \arg disk The opened UEFI filesystem to load from /// \arg desc The program descriptor identifying the program /// \arg add_module Also create a module for this loaded program -kernel::init::program * +bootproto::program * load_program( fs::file &disk, const program_desc &desc, @@ -53,7 +52,7 @@ load_module( /// Verify that a loaded ELF has the j6 kernel header /// \arg program The program to check for a header void -verify_kernel_header(kernel::init::program &program); +verify_kernel_header(bootproto::program &program); } // namespace loader } // namespace boot diff --git a/src/boot/main.cpp b/src/boot/main.cpp index 92ac848..2fae2af 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -7,6 +7,11 @@ #include #include +#include +#include +#include +#include + #include "allocator.h" #include "console.h" #include "error.h" @@ -19,19 +24,13 @@ #include "status.h" #include "video.h" -#include "kernel_args.h" - -namespace kernel { -#include "kernel_memory.h" -} - -namespace init = kernel::init; namespace boot { const loader::program_desc kern_desc = {L"kernel", L"jsix.elf"}; const loader::program_desc init_desc = {L"init server", L"srv.init.elf"}; const loader::program_desc fb_driver = {L"UEFI framebuffer driver", L"drv.uefi_fb.elf"}; +const loader::program_desc uart_driver = {L"Serial port driver", L"drv.uart.elf"}; const loader::program_desc panic_handler = {L"Serial panic handler", L"panic.serial.elf"}; @@ -44,13 +43,13 @@ const loader::program_desc extra_programs[] = { template void change_pointer(T *&pointer) { - pointer = offset_ptr(pointer, kernel::memory::page_offset); + pointer = util::offset_pointer(pointer, bootproto::mem::linear_offset); } /// The main procedure for the portion of the loader that runs while /// UEFI is still in control of the machine. (ie, while the loader still /// has access to boot services.) -init::args * +bootproto::args * uefi_preboot(uefi::handle image, uefi::system_table *st) { uefi::boot_services *bs = st->boot_services; @@ -61,11 +60,11 @@ uefi_preboot(uefi::handle image, uefi::system_table *st) hw::check_cpu_supported(); memory::init_pointer_fixup(bs, rs); - init::args *args = new init::args; - g_alloc.zero(args, sizeof(init::args)); + bootproto::args *args = new bootproto::args; + g_alloc.zero(args, sizeof(bootproto::args)); - args->magic = init::args_magic; - args->version = init::args_version; + args->magic = bootproto::args_magic; + args->version = bootproto::args_version; args->runtime_services = rs; args->acpi_table = hw::find_acpi_table(st); memory::mark_pointer_fixup(&args->runtime_services); @@ -77,7 +76,7 @@ uefi_preboot(uefi::handle image, uefi::system_table *st) /// Load the kernel and other programs from disk void -load_resources(init::args *args, video::screen *screen, uefi::handle image, uefi::boot_services *bs) +load_resources(bootproto::args *args, video::screen *screen, uefi::handle image, uefi::boot_services *bs) { status_line status {L"Loading programs"}; @@ -86,9 +85,11 @@ load_resources(init::args *args, video::screen *screen, uefi::handle image, uefi if (screen) { video::make_module(screen); loader::load_module(disk, fb_driver); + } else { + loader::load_module(disk, uart_driver); } - buffer symbol_table = loader::load_file(disk, {L"symbol table", L"symbol_table.dat"}); + util::buffer symbol_table = loader::load_file(disk, {L"symbol table", L"symbol_table.dat"}); args->symbol_table = reinterpret_cast(symbol_table.pointer); args->kernel = loader::load_program(disk, kern_desc, true); @@ -102,7 +103,7 @@ 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) +uefi_exit(bootproto::args *args, uefi::handle image, uefi::boot_services *bs) { status_line status {L"Exiting UEFI", nullptr, false}; @@ -131,14 +132,14 @@ efi_main(uefi::handle image, uefi::system_table *st) uefi::boot_services *bs = st->boot_services; console con(st->con_out); - init::allocation_register *allocs = nullptr; - init::modules_page *modules = nullptr; + bootproto::allocation_register *allocs = nullptr; + bootproto::modules_page *modules = nullptr; memory::allocator::init(allocs, modules, bs); video::screen *screen = video::pick_mode(bs); con.announce(); - init::args *args = uefi_preboot(image, st); + bootproto::args *args = uefi_preboot(image, st); load_resources(args, screen, image, bs); memory::efi_mem_map map = uefi_exit(args, image, st->boot_services); @@ -153,8 +154,8 @@ efi_main(uefi::handle image, uefi::system_table *st) memory::fix_frame_blocks(args); - init::entrypoint kentry = - reinterpret_cast(args->kernel->entrypoint); + bootproto::entrypoint kentry = + reinterpret_cast(args->kernel->entrypoint); //status.next(); hw::setup_control_regs(); diff --git a/src/boot/memory.cpp b/src/boot/memory.cpp index f3042c3..6cd43bb 100644 --- a/src/boot/memory.cpp +++ b/src/boot/memory.cpp @@ -4,9 +4,10 @@ #include #include +#include + #include "console.h" #include "error.h" -#include "kernel_memory.h" #include "memory.h" #include "memory_map.h" #include "paging.h" @@ -61,7 +62,7 @@ virtualize(void *pml4, efi_mem_map &map, uefi::runtime_services *rs) paging::add_current_mappings(reinterpret_cast(pml4)); for (auto &desc : map) - desc.virtual_start = desc.physical_start + ::memory::page_offset; + desc.virtual_start = desc.physical_start + bootproto::mem::linear_offset; // Write our new PML4 pointer to CR3 asm volatile ( "mov %0, %%cr3" :: "r" (pml4) ); diff --git a/src/boot/memory_map.cpp b/src/boot/memory_map.cpp index 0e3e31a..a59e794 100644 --- a/src/boot/memory_map.cpp +++ b/src/boot/memory_map.cpp @@ -1,9 +1,12 @@ #include #include +#include +#include +#include + #include "allocator.h" #include "error.h" -#include "kernel_memory.h" #include "memory.h" #include "memory_map.h" #include "paging.h" @@ -12,10 +15,10 @@ namespace boot { namespace memory { -using kernel::init::frame_block; -using kernel::init::frames_per_block; -using kernel::init::mem_entry; -using kernel::init::mem_type; +using bootproto::frame_block; +using bootproto::frames_per_block; +using bootproto::mem_entry; +using bootproto::mem_type; void @@ -89,7 +92,7 @@ memory_type_name(uefi::memory_type t) } static const wchar_t * -kernel_memory_type_name(kernel::init::mem_type t) +kernel_memory_type_name(bootproto::mem_type t) { return kernel_memory_type_names[static_cast(t)]; } @@ -103,7 +106,7 @@ can_merge(mem_entry &prev, mem_type type, uefi::memory_descriptor &next) prev.attr == (next.attribute & 0xffffffff); } -counted +util::counted build_kernel_map(efi_mem_map &map) { status_line status {L"Creating kernel memory map"}; @@ -200,8 +203,8 @@ build_kernel_map(efi_mem_map &map) inline size_t bitmap_size(size_t frames) { return (frames + 63) / 64; } inline size_t num_blocks(size_t frames) { return (frames + (frames_per_block-1)) / frames_per_block; } -counted -build_frame_blocks(const counted &kmap) +util::counted +build_frame_blocks(const util::counted &kmap) { status_line status {L"Creating kernel frame accounting map"}; @@ -232,7 +235,7 @@ build_frame_blocks(const counted &kmap) while (page_count) { frame_block *blk = next_block++; - blk->flags = static_cast(ent.attr); + blk->flags = static_cast(ent.attr); blk->base = base_addr; base_addr += frames_per_block * page_size; @@ -275,9 +278,9 @@ build_frame_blocks(const counted &kmap) } void -fix_frame_blocks(kernel::init::args *args) +fix_frame_blocks(bootproto::args *args) { - counted &blocks = args->frame_blocks; + util::counted &blocks = args->frame_blocks; size_t size = blocks.count * sizeof(frame_block); for (unsigned i = 0; i < blocks.count; ++i) @@ -288,13 +291,13 @@ fix_frame_blocks(kernel::init::args *args) // Map the frame blocks to the appropriate address paging::map_pages(args, addr, - ::memory::bitmap_start, pages, true, false); + bootproto::mem::bitmap_offset, pages, true, false); - uintptr_t offset = ::memory::bitmap_start - addr; + uintptr_t offset = bootproto::mem::bitmap_offset - addr; for (unsigned i = 0; i < blocks.count; ++i) { frame_block &blk = blocks[i]; - blk.bitmap = offset_ptr(blk.bitmap, offset); + blk.bitmap = util::offset_pointer(blk.bitmap, offset); } } diff --git a/src/boot/memory_map.h b/src/boot/memory_map.h index 69acb47..053e927 100644 --- a/src/boot/memory_map.h +++ b/src/boot/memory_map.h @@ -2,20 +2,19 @@ /// \file memory_map.h /// Memory-map related types and functions -#include "counted.h" -#include "pointer_manipulation.h" +#include +#include namespace uefi { struct boot_services; struct memory_descriptor; } -namespace kernel { -namespace init { +namespace bootproto { struct args; struct frame_block; struct mem_entry; -}} +} namespace boot { namespace memory { @@ -25,7 +24,7 @@ namespace memory { struct efi_mem_map { using desc = uefi::memory_descriptor; - using iterator = offset_iterator; + using iterator = util::offset_iterator; size_t length; ///< Total length of the map data size_t total; ///< Total allocated space for map data @@ -46,18 +45,18 @@ struct efi_mem_map inline iterator begin() { return iterator(entries, size); } /// Return an iterator to the end of the array - inline iterator end() { return offset_ptr(entries, length); } + inline iterator end() { return util::offset_pointer(entries, length); } }; /// Add the kernel's memory map as a module to the kernel args. /// \returns The uefi memory map used to build the kernel map -counted build_kernel_map(efi_mem_map &map); +util::counted build_kernel_map(efi_mem_map &map); /// Create the kernel frame allocation maps -counted build_frame_blocks(const counted &kmap); +util::counted build_frame_blocks(const util::counted &kmap); /// Map the frame allocation maps to the right spot and fix up pointers -void fix_frame_blocks(kernel::init::args *args); +void fix_frame_blocks(bootproto::args *args); } // namespace boot } // namespace memory diff --git a/src/boot/paging.cpp b/src/boot/paging.cpp index 7c929e9..f3af3c0 100644 --- a/src/boot/paging.cpp +++ b/src/boot/paging.cpp @@ -1,4 +1,7 @@ -#include "kernel_memory.h" +#include +#include +#include +#include #include "allocator.h" #include "console.h" @@ -6,7 +9,6 @@ #include "loader.h" #include "memory.h" #include "paging.h" -#include "pointer_manipulation.h" #include "status.h" namespace boot { @@ -14,8 +16,6 @@ namespace paging { using memory::alloc_type; using memory::page_size; -using ::memory::pml4e_kernel; -using ::memory::table_entries; // Flags: 0 0 0 1 0 0 0 0 0 0 0 1 = 0x0101 // IGN | | | | | | | | +- Present @@ -58,13 +58,13 @@ constexpr uint64_t table_flags = 0x003; inline void * -pop_pages(counted &pages, size_t count) +pop_pages(util::counted &pages, size_t count) { 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.pointer = util::offset_pointer(pages.pointer, count*page_size); pages.count -= count; return next; } @@ -81,7 +81,7 @@ public: page_entry_iterator( uintptr_t virt, page_table *pml4, - counted &pages) : + util::counted &pages) : m_pages(pages) { m_table[0] = pml4; @@ -137,17 +137,17 @@ private: } } - counted &m_pages; + util::counted &m_pages; page_table *m_table[D]; uint16_t m_index[D]; }; static void -add_offset_mappings(page_table *pml4, counted &pages) +add_offset_mappings(page_table *pml4, util::counted &pages) { uintptr_t phys = 0; - uintptr_t virt = ::memory::page_offset; // Start of offset-mapped area + uintptr_t virt = bootproto::mem::linear_offset; // Start of offset-mapped area size_t page_count = 64 * 1024; // 64 TiB of 1 GiB pages constexpr size_t GiB = 0x40000000ull; @@ -164,9 +164,12 @@ add_offset_mappings(page_table *pml4, counted &pages) } static void -add_kernel_pds(page_table *pml4, counted &pages) +add_kernel_pds(page_table *pml4, util::counted &pages) { - for (unsigned i = pml4e_kernel; i < table_entries; ++i) + constexpr unsigned start = arch::kernel_root_index; + constexpr unsigned end = arch::table_entries; + + for (unsigned i = start; i < end; ++i) pml4->set(i, pop_pages(pages, 1), table_flags); } @@ -178,7 +181,8 @@ add_current_mappings(page_table *new_pml4) asm volatile ( "mov %%cr3, %0" : "=r" (old_pml4) ); // Only copy mappings in the lower half - for (int i = 0; i < ::memory::pml4e_kernel; ++i) { + constexpr unsigned halfway = arch::kernel_root_index; + for (int i = 0; i < halfway; ++i) { uint64_t entry = old_pml4->entries[i]; if (entry & 1) new_pml4->entries[i] = entry; @@ -186,7 +190,7 @@ add_current_mappings(page_table *new_pml4) } void -allocate_tables(kernel::init::args *args) +allocate_tables(bootproto::args *args) { status_line status(L"Allocating initial page tables"); @@ -221,7 +225,7 @@ constexpr bool has_flag(E set, E flag) { void map_pages( - kernel::init::args *args, + bootproto::args *args, uintptr_t phys, uintptr_t virt, size_t count, bool write_flag, bool exe_flag) { @@ -251,10 +255,10 @@ map_pages( void map_section( - kernel::init::args *args, - const kernel::init::program_section §ion) + bootproto::args *args, + const bootproto::program_section §ion) { - using kernel::init::section_flags; + using bootproto::section_flags; map_pages( args, @@ -267,8 +271,8 @@ map_section( void map_program( - kernel::init::args *args, - kernel::init::program &program) + bootproto::args *args, + bootproto::program &program) { for (auto §ion : program.sections) paging::map_section(args, section); diff --git a/src/boot/paging.h b/src/boot/paging.h index 498f623..32e25bd 100644 --- a/src/boot/paging.h +++ b/src/boot/paging.h @@ -3,7 +3,7 @@ /// Page table structure and related definitions #include #include -#include "kernel_args.h" +#include namespace boot { namespace paging { @@ -30,7 +30,7 @@ struct page_table /// and kernel args' `page_table_cache` and `num_free_tables` are updated with /// the leftover space. /// \arg args The kernel args struct, used for the page table cache and pml4 -void allocate_tables(kernel::init::args *args); +void allocate_tables(bootproto::args *args); /// Copy existing page table entries to a new page table. Does not do a deep /// copy - the new PML4 is updated to point to the existing next-level page @@ -46,7 +46,7 @@ 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, + bootproto::args *args, uintptr_t phys, uintptr_t virt, size_t count, bool write_flag, bool exe_flag); @@ -55,8 +55,8 @@ void map_pages( /// \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::program &program); + bootproto::args *args, + bootproto::program &program); } // namespace paging } // namespace boot diff --git a/src/boot/status.cpp b/src/boot/status.cpp index c7fcf90..7c84bb4 100644 --- a/src/boot/status.cpp +++ b/src/boot/status.cpp @@ -4,7 +4,6 @@ #include "console.h" #include "error.h" -#include "init_args.h" #include "status.h" #include "video.h" diff --git a/src/boot/video.cpp b/src/boot/video.cpp index 8d89137..9b0e73f 100644 --- a/src/boot/video.cpp +++ b/src/boot/video.cpp @@ -5,17 +5,16 @@ #include "allocator.h" #include "console.h" #include "error.h" -#include "init_args.h" #include "video.h" namespace boot { namespace video { -using kernel::init::fb_layout; -using kernel::init::fb_type; -using kernel::init::module_flags; -using kernel::init::module_framebuffer; -using kernel::init::module_type; +using bootproto::fb_layout; +using bootproto::fb_type; +using bootproto::module_flags; +using bootproto::module_framebuffer; +using bootproto::module_type; static uefi::protos::graphics_output * get_gop(uefi::boot_services *bs) @@ -109,7 +108,7 @@ pick_mode(uefi::boot_services *bs) void make_module(screen *s) { - using kernel::init::module_framebuffer; + using bootproto::module_framebuffer; module_framebuffer *modfb = g_alloc.allocate_module(); modfb->mod_type = module_type::framebuffer; modfb->type = fb_type::uefi; diff --git a/src/boot/video.h b/src/boot/video.h index d43ce70..d3bc6bf 100644 --- a/src/boot/video.h +++ b/src/boot/video.h @@ -5,7 +5,8 @@ #include #include -#include "init_args.h" +#include +#include namespace uefi { struct boot_services; @@ -14,11 +15,11 @@ namespace uefi { namespace boot { namespace video { -using kernel::init::video_mode; -using layout = kernel::init::fb_layout; +using bootproto::video_mode; +using layout = bootproto::fb_layout; struct screen { - buffer framebuffer; + util::buffer framebuffer; video_mode mode; }; diff --git a/src/include/arch/amd64/memory.h b/src/include/arch/amd64/memory.h new file mode 100644 index 0000000..a31774a --- /dev/null +++ b/src/include/arch/amd64/memory.h @@ -0,0 +1,31 @@ +#pragma once +/// \file arch/amd64/memory.h +/// Architecture-specific constants related to memory and paging + +#include + +namespace arch { + +/// Size of a single page frame. +constexpr size_t frame_size = 0x1000; + +/// Number of bits of addressing within a page +constexpr size_t frame_bits = 12; + +/// Number of bits mapped per page table level +constexpr size_t table_bits = 9; + +/// Number of page_table entries +constexpr unsigned table_entries = 512; + +/// First index in the root page table for kernel space +constexpr unsigned kernel_root_index = table_entries / 2; + +/// Number of page table levels +/// TODO: Add five-level paging support +constexpr unsigned page_table_levels = 4; + +/// Start of kernel memory. +constexpr uintptr_t kernel_offset = 0ull - (1ull << (page_table_levels * table_bits + frame_bits - 1)); + +} // namespace arch diff --git a/src/include/arch/memory.h b/src/include/arch/memory.h new file mode 100644 index 0000000..7a0e33f --- /dev/null +++ b/src/include/arch/memory.h @@ -0,0 +1,9 @@ +#pragma once +/// \file arch/memory.h +/// Include architecture-specific constants related to memory and paging + +#if defined(__amd64__) || defined(__x86_64__) +#include +#else +#error Unsupported platform. +#endif diff --git a/src/include/kernel_memory.h b/src/include/kernel_memory.h deleted file mode 100644 index f3b1b36..0000000 --- a/src/include/kernel_memory.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once -/// \file kernel_memory.h -/// Constants related to the kernel's memory layout - -#include -#include - -namespace memory { - - /// Size of a single page frame. - constexpr size_t frame_size = 0x1000; - - /// Number of bits of addressing within a page - constexpr size_t frame_bits = 12; - - /// Start of kernel memory. - constexpr uintptr_t kernel_offset = 0xffff800000000000ull; - - /// 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 buffer - constexpr unsigned kernel_buffer_pages = 16; - - /// 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; - - /// 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; - - /// 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; - - /// 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; - - /// First kernel space PML4 entry - constexpr unsigned pml4e_kernel = 256; - - /// First offset-mapped space PML4 entry - constexpr unsigned pml4e_offset = 384; - - /// 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; } - - /// 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)); - } - - /// 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 page - inline uintptr_t page_align_up(uintptr_t a) { return page_align_down(a-1) + frame_size; } - -} // namespace memory diff --git a/src/kernel/acpi_tables.h b/src/kernel/acpi_tables.h index a9665fb..383d855 100644 --- a/src/kernel/acpi_tables.h +++ b/src/kernel/acpi_tables.h @@ -3,7 +3,7 @@ #include #include -#include +#include // for byteswap32 #include struct acpi_table_header @@ -22,7 +22,7 @@ struct acpi_table_header } __attribute__ ((packed)); #define TABLE_HEADER(signature) \ - static constexpr uint32_t type_id = util::byteswap(signature); \ + static constexpr uint32_t type_id = util::byteswap32(signature); \ acpi_table_header header; diff --git a/src/kernel/apic.cpp b/src/kernel/apic.cpp index d897b1d..5fab458 100644 --- a/src/kernel/apic.cpp +++ b/src/kernel/apic.cpp @@ -3,8 +3,8 @@ #include "clock.h" #include "interrupts.h" #include "io.h" -#include "kernel_memory.h" #include "log.h" +#include "memory.h" uint64_t lapic::s_ticks_per_us = 0; @@ -51,7 +51,7 @@ ioapic_write(uint32_t volatile *base, uint8_t reg, uint32_t value) } apic::apic(uintptr_t base) : - m_base(memory::to_virtual(base)) + m_base(mem::to_virtual(base)) { } diff --git a/src/kernel/cpu.cpp b/src/kernel/cpu.cpp index 6f0fc07..64d1c47 100644 --- a/src/kernel/cpu.cpp +++ b/src/kernel/cpu.cpp @@ -6,7 +6,6 @@ #include "device_manager.h" #include "gdt.h" #include "idt.h" -#include "kernel_memory.h" #include "log.h" #include "msr.h" #include "objects/vm_area.h" diff --git a/src/kernel/device_manager.cpp b/src/kernel/device_manager.cpp index 049453b..0678b5b 100644 --- a/src/kernel/device_manager.cpp +++ b/src/kernel/device_manager.cpp @@ -1,5 +1,7 @@ #include #include +#include // for checksum +#include #include "assert.h" #include "acpi_tables.h" @@ -8,7 +10,6 @@ #include "console.h" #include "device_manager.h" #include "interrupts.h" -#include "kernel_memory.h" #include "log.h" #include "memory.h" #include "objects/endpoint.h" @@ -47,7 +48,7 @@ struct acpi2_rsdp bool acpi_table_header::validate(uint32_t expected_type) const { - if (::checksum(this, length) != 0) return false; + if (util::checksum(this, length) != 0) return false; return !expected_type || (expected_type == type); } @@ -75,14 +76,14 @@ device_manager::parse_acpi(const void *root_table) { kassert(root_table != 0, "ACPI root table pointer is null."); - const acpi1_rsdp *acpi1 = memory::to_virtual( + const acpi1_rsdp *acpi1 = mem::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"); - uint8_t sum = checksum(acpi1, sizeof(acpi1_rsdp), 0); + uint8_t sum = util::checksum(acpi1, sizeof(acpi1_rsdp), 0); kassert(sum == 0, "ACPI 1.0 RSDP checksum mismatch."); kassert(acpi1->revision > 1, "ACPI 1.0 not supported."); @@ -90,10 +91,10 @@ device_manager::parse_acpi(const void *root_table) const acpi2_rsdp *acpi2 = reinterpret_cast(acpi1); - sum = checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp)); + sum = util::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(mem::to_virtual(acpi2->xsdt_address)); } const device_manager::apic_nmi * @@ -142,7 +143,7 @@ device_manager::load_xsdt(const acpi_table_header *header) 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]); + mem::to_virtual(xsdt->headers[i]); put_sig(sig, header->type); log::debug(logs::device, " Found table %s", sig); @@ -212,8 +213,8 @@ device_manager::load_apic(const acpi_table_header *header) switch (type) { case 0: { // Local APIC - uint8_t uid = read_from(p+2); - uint8_t id = read_from(p+3); + uint8_t uid = util::read_from(p+2); + uint8_t id = util::read_from(p+3); m_apic_ids.append(id); log::debug(logs::device, " Local APIC uid %x id %x", uid, id); @@ -221,8 +222,8 @@ device_manager::load_apic(const acpi_table_header *header) break; case 1: { // I/O APIC - uintptr_t base = read_from(p+4); - uint32_t base_gsi = read_from(p+8); + uintptr_t base = util::read_from(p+4); + uint32_t base_gsi = util::read_from(p+8); m_ioapics.emplace(base, base_gsi); log::debug(logs::device, " IO APIC gsi %x base %x", base_gsi, base); @@ -231,9 +232,9 @@ device_manager::load_apic(const acpi_table_header *header) case 2: { // Interrupt source override irq_override o; - o.source = read_from(p+3); - o.gsi = read_from(p+4); - o.flags = read_from(p+8); + o.source = util::read_from(p+3); + o.gsi = util::read_from(p+4); + o.flags = util::read_from(p+8); m_overrides.append(o); log::debug(logs::device, " Intr source override IRQ %d -> %d Pol %d Tri %d", @@ -243,9 +244,9 @@ device_manager::load_apic(const acpi_table_header *header) case 4: {// LAPIC NMI apic_nmi nmi; - nmi.cpu = read_from(p + 2); - nmi.lint = read_from(p + 5); - nmi.flags = read_from(p + 3); + nmi.cpu = util::read_from(p + 2); + nmi.lint = util::read_from(p + 5); + nmi.flags = util::read_from(p + 3); m_nmis.append(nmi); log::debug(logs::device, " LAPIC NMI Proc %02x LINT%d Pol %d Tri %d", @@ -279,7 +280,7 @@ device_manager::load_mcfg(const acpi_table_header *header) 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].base = mem::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); @@ -308,7 +309,7 @@ device_manager::load_hpet(const acpi_table_header *header) 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)); + reinterpret_cast(hpet->base_address.address + mem::linear_offset)); } void diff --git a/src/kernel/frame_allocator.cpp b/src/kernel/frame_allocator.cpp index 8228e42..9152ede 100644 --- a/src/kernel/frame_allocator.cpp +++ b/src/kernel/frame_allocator.cpp @@ -1,10 +1,11 @@ +#include + #include "assert.h" #include "frame_allocator.h" -#include "kernel_args.h" -#include "kernel_memory.h" #include "log.h" +#include "memory.h" -using memory::frame_size; +using mem::frame_size; frame_allocator & @@ -14,7 +15,7 @@ frame_allocator::get() return g_frame_allocator; } -frame_allocator::frame_allocator(kernel::init::frame_block *frames, size_t count) : +frame_allocator::frame_allocator(bootproto::frame_block *frames, size_t count) : m_blocks {frames}, m_count {count} { diff --git a/src/kernel/frame_allocator.h b/src/kernel/frame_allocator.h index f276e27..4f8597c 100644 --- a/src/kernel/frame_allocator.h +++ b/src/kernel/frame_allocator.h @@ -5,16 +5,15 @@ #include #include -namespace kernel { -namespace init { +namespace bootproto { struct frame_block; -}} +} /// Allocator for physical memory frames class frame_allocator { public: - using frame_block = kernel::init::frame_block; + using frame_block = bootproto::frame_block; /// Constructor /// \arg blocks The bootloader-supplied frame bitmap block list diff --git a/src/kernel/heap_allocator.cpp b/src/kernel/heap_allocator.cpp index 2195816..1a8051b 100644 --- a/src/kernel/heap_allocator.cpp +++ b/src/kernel/heap_allocator.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include "assert.h" @@ -44,8 +45,8 @@ struct heap_allocator::mem_header set_next(nullptr); } - inline mem_header * next() { return mask_pointer(m_next, 0x3f); } - inline mem_header * prev() { return mask_pointer(m_prev, 0x3f); } + inline mem_header * next() { return util::mask_pointer(m_next, 0x3f); } + inline mem_header * prev() { return util::mask_pointer(m_prev, 0x3f); } inline mem_header * buddy() const { return reinterpret_cast( @@ -155,7 +156,7 @@ heap_allocator::ensure_block(unsigned order) } else { mem_header *orig = pop_free(order + 1); if (orig) { - mem_header *next = offset_pointer(orig, 1 << order); + mem_header *next = util::offset_pointer(orig, 1 << order); new (next) mem_header(orig, nullptr, order); orig->set_next(next); diff --git a/src/kernel/hpet.cpp b/src/kernel/hpet.cpp index 8250b77..bc460ba 100644 --- a/src/kernel/hpet.cpp +++ b/src/kernel/hpet.cpp @@ -1,5 +1,3 @@ -#include "kernel_memory.h" - #include "assert.h" #include "device_manager.h" #include "hpet.h" diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index de661de..9d519a5 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -1,7 +1,5 @@ #include -#include "kernel_memory.h" -#include "printf/printf.h" #include "assert.h" #include "cpu.h" @@ -9,14 +7,16 @@ #include "idt.h" #include "interrupts.h" #include "io.h" +#include "memory.h" #include "objects/process.h" +#include "printf/printf.h" #include "scheduler.h" #include "vm_space.h" static const uint16_t PIC1 = 0x20; static const uint16_t PIC2 = 0xa0; -constexpr uintptr_t apic_eoi_addr = 0xfee000b0 + ::memory::page_offset; +constexpr uintptr_t apic_eoi_addr = 0xfee000b0 + mem::linear_offset; extern "C" { void isr_handler(cpu_state*); @@ -119,7 +119,7 @@ isr_handler(cpu_state *regs) uintptr_t cr2 = 0; __asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2)); - bool user = cr2 < memory::kernel_offset; + bool user = cr2 < mem::kernel_offset; vm_space::fault_type ft = static_cast(regs->errorcode); diff --git a/src/kernel/kernel.module b/src/kernel/kernel.module index 9d2ad01..1cfdaa6 100644 --- a/src/kernel/kernel.module +++ b/src/kernel/kernel.module @@ -5,7 +5,7 @@ kernel = module("kernel", default = True, output = "jsix.elf", targets = [ "kernel" ], - deps = [ "util", "cpu" ], + deps = [ "util", "cpu", "bootproto" ], includes = [ "." ], sources = [ "apic.cpp", @@ -15,6 +15,7 @@ kernel = module("kernel", "clock.cpp", "console.cpp", "cpprt.cpp", + "cpu.cpp", "debug.cpp", "debug.s", "device_manager.cpp", @@ -29,6 +30,7 @@ kernel = module("kernel", "io.cpp", "log.cpp", "logger.cpp", + "main.cpp", "memory.cpp", "memory_bootstrap.cpp", "msr.cpp", @@ -45,6 +47,7 @@ kernel = module("kernel", "printf/printf.c", "scheduler.cpp", "serial.cpp", + "syscall.s", "syscalls/channel.cpp", "syscalls/endpoint.cpp", "syscalls/object.cpp", @@ -58,14 +61,41 @@ kernel = module("kernel", ]) from glob import glob -definitions = glob('definitions/**/*.def', recursive=True) -sysinc = kernel.add_input("syscalls.inc.cog", deps=definitions) -kernel.add_input("syscall.s", deps=[sysinc]) +from os.path import join +layout = join(source_root, "definitions/memory_layout.csv") +definitions = glob('definitions/**/*.def', recursive=True) + +sysinc = kernel.add_input("syscalls.inc.cog", deps=definitions) + +memh = kernel.add_input("memory.h.cog", deps=[layout]) sysh = kernel.add_input("syscall.h.cog", deps=definitions) sysc = kernel.add_input("syscall.cpp.cog", deps=definitions + [sysh]) -kernel.add_input("main.cpp", deps=[sysh]) -kernel.add_input("cpu.cpp", deps=[sysh]) +kernel.add_depends(["syscall.s"], [sysinc]) +kernel.add_depends(["main.cpp", "cpu.cpp"], [sysh]) +kernel.add_depends(["main.cpp", "cpu.cpp"], [sysh]) + +kernel.add_depends([ + "apic.cpp", + "device_manager.cpp", + "frame_allocator.cpp", + "heap_allocator.cpp", + "heap_allocator.h", + "interrupts.cpp", + "log.cpp", + "main.cpp", + "memory_bootstrap.cpp", + "memory.cpp", + "objects/channel.cpp", + "objects/thread.cpp", + "objects/vm_area.cpp", + "page_table.cpp", + "page_tree.cpp", + "syscalls/system.cpp", + "tss.cpp", + "vm_space.cpp", + ], + [memh]) kernel.variables['ldflags'] = ["${ldflags}", "-T", "${source_root}/src/kernel/kernel.ld"] diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 2cf60b1..bf41298 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -2,10 +2,9 @@ #include #include +#include #include #include -#include -#include #include "apic.h" #include "assert.h" @@ -19,6 +18,7 @@ #include "interrupts.h" #include "io.h" #include "log.h" +#include "memory.h" #include "msr.h" #include "objects/channel.h" #include "objects/event.h" @@ -36,7 +36,7 @@ #endif extern "C" { - void kernel_main(kernel::init::args *args); + void kernel_main(bootproto::args *args); void (*__ctors)(void); void (*__ctors_end)(void); void long_ap_startup(cpu_data *cpu); @@ -45,15 +45,13 @@ extern "C" { void init_ap_trampoline(void*, cpu_data *, void (*)()); } -using namespace kernel; - volatile size_t ap_startup_count; static bool scheduler_ready = false; /// Bootstrap the memory managers. -void memory_initialize_pre_ctors(init::args &kargs); -void memory_initialize_post_ctors(init::args &kargs); -void load_init_server(init::program &program, uintptr_t modules_address); +void memory_initialize_pre_ctors(bootproto::args &kargs); +void memory_initialize_post_ctors(bootproto::args &kargs); +void load_init_server(bootproto::program &program, uintptr_t modules_address); unsigned start_aps(lapic &apic, const util::vector &ids, void *kpml4); @@ -80,11 +78,11 @@ run_constructors() } void -kernel_main(init::args *args) +kernel_main(bootproto::args *args) { if (args->panic) { IDT::set_nmi_handler(args->panic->entrypoint); - panic::symbol_table = args->symbol_table | memory::page_offset; + panic::symbol_table = args->symbol_table | mem::linear_offset; } init_console(); @@ -108,7 +106,7 @@ kernel_main(init::args *args) cpu->rsp0 = idle_stack_end; cpu_early_init(cpu); - kassert(args->magic == init::args_magic, + kassert(args->magic == bootproto::args_magic, "Bad kernel args magic number"); log::debug(logs::boot, "jsix init args are at: %016lx", args); @@ -193,8 +191,8 @@ kernel_main(init::args *args) unsigned start_aps(lapic &apic, const util::vector &ids, void *kpml4) { - using memory::frame_size; - using memory::kernel_stack_pages; + using mem::frame_size; + using mem::kernel_stack_pages; extern size_t ap_startup_code_size; extern process &g_kernel_process; diff --git a/src/kernel/memory.cpp b/src/kernel/memory.cpp index 6a8fd49..1a5c4c2 100644 --- a/src/kernel/memory.cpp +++ b/src/kernel/memory.cpp @@ -26,12 +26,3 @@ memcpy(void *dest, const void *src, size_t n) } } - -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; -} diff --git a/src/kernel/memory.h b/src/kernel/memory.h deleted file mode 100644 index 7faf59d..0000000 --- a/src/kernel/memory.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include - - -void * operator new (size_t, void *p) noexcept; - -/// Allocate from the default allocator. -/// \arg size The size in bytes requested -/// \returns A pointer to the newly allocated memory, -/// or nullptr on error -void * kalloc(size_t size); - -/// Free memory allocated by `kalloc`. -/// \arg p Pointer that was returned from a `kalloc` call -void kfree(void *p); - -/// Read a value of type T from a location in memory -/// \arg p The location in memory to read -/// \returns The value at the given location cast to T -template -inline T read_from(const void *p) -{ - return *reinterpret_cast(p); -} - -/// Get a pointer that's offset from another pointer -/// \arg p The base pointer -/// \arg n The offset in bytes -/// \returns The offset pointer -template -inline T * offset_pointer(T *p, ptrdiff_t n) -{ - return reinterpret_cast(reinterpret_cast(p) + n); -} - -/// Return a pointer with the given bits masked out -/// \arg p The original pointer -/// \arg mask A bitmask of bits to clear from p -/// \returns The masked pointer -template -inline T* mask_pointer(T *p, uintptr_t mask) -{ - return reinterpret_cast(reinterpret_cast(p) & ~mask); -} - -/// Do a simple byte-wise checksum of an area of memory. -/// \arg p The start of the memory region -/// \arg len The number of bytes in the region -/// \arg off An optional offset into the region -uint8_t checksum(const void *p, size_t len, size_t off = 0); diff --git a/src/kernel/memory.h.cog b/src/kernel/memory.h.cog new file mode 100644 index 0000000..37a3673 --- /dev/null +++ b/src/kernel/memory.h.cog @@ -0,0 +1,79 @@ +#pragma once +// vim: ft=cpp + +/// \file bootproto/memory.h +/// Import memory layout constants necessary for boot + +#include +#include + +#include + +void * operator new (size_t, void *p) noexcept; + +/// Allocate from the default allocator. +/// \arg size The size in bytes requested +/// \returns A pointer to the newly allocated memory, +/// or nullptr on error +void * kalloc(size_t size); + +/// Free memory allocated by `kalloc`. +/// \arg p Pointer that was returned from a `kalloc` call +void kfree(void *p); + +/// Kernel space virtual memory layout +namespace mem { + +using arch::frame_size; +using arch::kernel_offset; + +/// 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; + +/*[[[cog code generation +from os.path import join +from memory import Layout + +layout = Layout(join(definitions_path, "memory_layout.csv")) +l = max([len(r.name) for r in layout.regions]) + +for region in layout.regions: + cog.outl(f"constexpr size_t {region.name:>{l}}_size = {region.size:#14x};") + +cog.outl("") + +for region in layout.regions: + cog.outl(f"constexpr uintptr_t {region.name:>{l}}_offset = {region.start:#x};") + +]]]*/ +///[[[end]]] + +/// Helper to determine if a physical address can be accessed +/// through the linear_offset area. +constexpr bool linear_mappable(uintptr_t a) { return (a & linear_offset) == 0; } + +/// Convert a physical address to a virtual one (in the linear-mapped area) +template T * to_virtual(uintptr_t a) { + return reinterpret_cast(a|linear_offset); +} + +/// Convert a physical address to a virtual one (in the linear-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 +constexpr size_t page_count(size_t bytes) { return ((bytes - 1) >> 12) + 1; } + +/// Get the given address, aligned to the next lowest page +constexpr uintptr_t page_align_down(uintptr_t a) { return a & ~(frame_size-1); } + +/// Get the given address, aligned to the next page +constexpr uintptr_t page_align_up(uintptr_t a) { return page_align_down(a-1) + frame_size; } + +} // namespace mem diff --git a/src/kernel/memory_bootstrap.cpp b/src/kernel/memory_bootstrap.cpp index 4d17c16..3061f25 100644 --- a/src/kernel/memory_bootstrap.cpp +++ b/src/kernel/memory_bootstrap.cpp @@ -1,8 +1,9 @@ #include +#include +#include #include #include -#include #include #include "assert.h" @@ -12,6 +13,7 @@ #include "heap_allocator.h" #include "io.h" #include "log.h" +#include "memory.h" #include "msr.h" #include "objects/process.h" #include "objects/thread.h" @@ -19,18 +21,12 @@ #include "objects/vm_area.h" #include "vm_space.h" -using memory::heap_start; -using memory::kernel_max_heap; +namespace bootproto { + is_bitfield(section_flags); +} -namespace kernel { -namespace init { -is_bitfield(section_flags); -}} - -using kernel::init::allocation_register; -using kernel::init::section_flags; - -using namespace kernel; +using bootproto::allocation_register; +using bootproto::section_flags; extern "C" void initialize_main_thread(); extern "C" uintptr_t initialize_main_user_stack(); @@ -51,9 +47,9 @@ static util::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, + mem::buffers_offset, + mem::kernel_buffer_pages, + mem::buffers_size, vm_flags::write}; void * operator new(size_t size) { return g_kernel_heap.allocate(size); } @@ -67,26 +63,26 @@ 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 mem::page_align_down(reinterpret_cast(p)); } void -memory_initialize_pre_ctors(init::args &kargs) +memory_initialize_pre_ctors(bootproto::args &kargs) { - using kernel::init::frame_block; + using bootproto::frame_block; page_table *kpml4 = static_cast(kargs.pml4); - new (&g_kernel_heap) heap_allocator {heap_start, kernel_max_heap}; + new (&g_kernel_heap) heap_allocator {mem::heap_offset, mem::heap_size}; - frame_block *blocks = reinterpret_cast(memory::bitmap_start); + frame_block *blocks = reinterpret_cast(mem::bitmap_offset); 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) + if (alloc.type != bootproto::allocation_type::none) g_frame_allocator.used(alloc.address, alloc.count); reg = reg->next; } @@ -95,27 +91,27 @@ memory_initialize_pre_ctors(init::args &kargs) vm_space &vm = kp->space(); vm_area *heap = new (&g_kernel_heap_area) - vm_area_untracked(kernel_max_heap, vm_flags::write); + vm_area_untracked(mem::heap_size, vm_flags::write); - vm.add(heap_start, heap); + vm.add(mem::heap_offset, heap); vm_area *stacks = new (&g_kernel_stacks) vm_area_guarded { - memory::stacks_start, - memory::kernel_stack_pages, - memory::kernel_max_stacks, + mem::stacks_offset, + mem::kernel_stack_pages, + mem::stacks_size, vm_flags::write}; - vm.add(memory::stacks_start, &g_kernel_stacks); + vm.add(mem::stacks_offset, &g_kernel_stacks); // Clean out any remaning bootloader page table entries - for (unsigned i = 0; i < memory::pml4e_kernel; ++i) + for (unsigned i = 0; i < arch::kernel_root_index; ++i) kpml4->entries[i] = 0; } void -memory_initialize_post_ctors(init::args &kargs) +memory_initialize_post_ctors(bootproto::args &kargs) { vm_space &vm = vm_space::kernel_space(); - vm.add(memory::buffers_start, &g_kernel_buffers); + vm.add(mem::buffers_offset, &g_kernel_buffers); g_frame_allocator.free( get_physical_page(kargs.page_tables.pointer), @@ -179,7 +175,7 @@ log_mtrrs() void -load_init_server(init::program &program, uintptr_t modules_address) +load_init_server(bootproto::program &program, uintptr_t modules_address) { process *p = new process; p->add_handle(&system::get()); diff --git a/src/kernel/objects/channel.cpp b/src/kernel/objects/channel.cpp index eec967f..a5bb72e 100644 --- a/src/kernel/objects/channel.cpp +++ b/src/kernel/objects/channel.cpp @@ -1,13 +1,13 @@ #include #include "assert.h" -#include "kernel_memory.h" +#include "memory.h" #include "objects/channel.h" #include "objects/vm_area.h" extern vm_area_guarded g_kernel_buffers; -constexpr size_t buffer_bytes = memory::kernel_buffer_pages * memory::frame_size; +constexpr size_t buffer_bytes = mem::kernel_buffer_pages * mem::frame_size; channel::channel() : m_len(0), diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index 4e26dc2..70c3d56 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -1,4 +1,5 @@ #include +#include #include "cpu.h" #include "log.h" @@ -42,7 +43,7 @@ thread::from_tcb(TCB *tcb) { static ptrdiff_t offset = -1 * static_cast(offsetof(thread, m_tcb)); - return reinterpret_cast(offset_pointer(tcb, offset)); + return reinterpret_cast(util::offset_pointer(tcb, offset)); } thread & thread::current() { return *current_cpu().thread; } @@ -196,8 +197,8 @@ thread::add_thunk_user(uintptr_t rip3, uintptr_t rip0, uint64_t flags) void thread::setup_kernel_stack() { - using memory::frame_size; - using memory::kernel_stack_pages; + using mem::frame_size; + using mem::kernel_stack_pages; static constexpr size_t stack_bytes = kernel_stack_pages * frame_size; constexpr unsigned null_frame_entries = 2; diff --git a/src/kernel/objects/vm_area.cpp b/src/kernel/objects/vm_area.cpp index c38f3da..d8bd1a2 100644 --- a/src/kernel/objects/vm_area.cpp +++ b/src/kernel/objects/vm_area.cpp @@ -1,12 +1,12 @@ -#include "kernel_memory.h" #include "assert.h" #include "frame_allocator.h" +#include "memory.h" #include "objects/vm_area.h" #include "page_tree.h" #include "vm_space.h" -using memory::frame_size; +using mem::frame_size; vm_area::vm_area(size_t size, vm_flags flags) : m_size {size}, @@ -74,7 +74,7 @@ vm_area_fixed::~vm_area_fixed() if (m_flags && vm_flags::mmio) return; - size_t pages = memory::page_count(m_size); + size_t pages = mem::page_count(m_size); frame_allocator::get().free(m_start, pages); } @@ -145,7 +145,7 @@ vm_area_open::get_page(uintptr_t offset, uintptr_t &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}, + m_next {mem::frame_size}, vm_area_open {size, flags} { } @@ -160,7 +160,7 @@ vm_area_guarded::get_section() } uintptr_t addr = m_next; - m_next += (m_pages + 1) * memory::frame_size; + m_next += (m_pages + 1) * mem::frame_size; return m_start + addr; } diff --git a/src/kernel/objects/vm_area.h b/src/kernel/objects/vm_area.h index 9a95100..6a22ff2 100644 --- a/src/kernel/objects/vm_area.h +++ b/src/kernel/objects/vm_area.h @@ -9,7 +9,6 @@ #include #include -#include "kernel_memory.h" #include "objects/kobject.h" class page_tree; diff --git a/src/kernel/page_table.cpp b/src/kernel/page_table.cpp index 96d963b..c969b96 100644 --- a/src/kernel/page_table.cpp +++ b/src/kernel/page_table.cpp @@ -1,13 +1,14 @@ #include +#include #include "assert.h" #include "console.h" -#include "frame_allocator.h" -#include "kernel_memory.h" #include "memory.h" +#include "frame_allocator.h" #include "page_table.h" -using memory::page_offset; +using mem::frame_size; +using mem::linear_offset; using level = page_table::level; free_page_header * page_table::s_page_cache = nullptr; @@ -123,7 +124,7 @@ page_table::iterator::check_table(level l) const uint64_t parent = entry(l - 1); if (parent & 1) { - table(l) = reinterpret_cast(page_offset | (parent & ~0xfffull)); + table(l) = reinterpret_cast(linear_offset | (parent & ~0xfffull)); return true; } return false; @@ -138,11 +139,11 @@ page_table::iterator::ensure_table(level l) if (check_table(l)) return; page_table *table = page_table::get_table_page(); - uintptr_t phys = reinterpret_cast(table) & ~page_offset; + uintptr_t phys = reinterpret_cast(table) & ~linear_offset; uint64_t &parent = entry(l - 1); flag flags = table_flags; - if (m_index[0] < memory::pml4e_kernel) + if (m_index[0] < arch::kernel_root_index) flags |= flag::user; m_table[unsigned(l)] = table; @@ -161,14 +162,14 @@ page_table::get(int i, uint16_t *flags) const if (flags) *flags = entry & 0xfffull; - return reinterpret_cast((entry & ~0xfffull) + page_offset); + return reinterpret_cast((entry & ~0xfffull) + linear_offset); } void page_table::set(int i, page_table *p, uint16_t flags) { entries[i] = - (reinterpret_cast(p) - page_offset) | + (reinterpret_cast(p) - linear_offset) | (flags & 0xfff); } @@ -192,7 +193,7 @@ page_table::get_table_page() --s_cache_count; } - memset(page, 0, memory::frame_size); + memset(page, 0, frame_size); return reinterpret_cast(page); } @@ -219,14 +220,14 @@ page_table::fill_table_page_cache() kassert(phys, "Got physical page 0 as a page table"); free_page_header *start = - memory::to_virtual(phys); + mem::to_virtual(phys); for (int i = 0; i < n - 1; ++i) - offset_pointer(start, i * memory::frame_size) - ->next = offset_pointer(start, (i+1) * memory::frame_size); + util::offset_pointer(start, i * frame_size) + ->next = util::offset_pointer(start, (i+1) * frame_size); free_page_header *end = - offset_pointer(start, (n-1) * memory::frame_size); + util::offset_pointer(start, (n-1) * frame_size); end->next = s_page_cache; s_page_cache = start; @@ -238,14 +239,14 @@ void page_table::free(page_table::level l) { unsigned last = l == level::pml4 - ? memory::pml4e_kernel - : memory::table_entries; + ? arch::kernel_root_index + : arch::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)]); + size_t count = mem::page_count(entry_sizes[unsigned(l)]); fa.free(entries[i] & ~0xfffull, count); } else { get(i)->free(l + 1); @@ -261,7 +262,7 @@ page_table::dump(page_table::level lvl, bool recurse) console *cons = console::get(); cons->printf("\nLevel %d page table @ %lx:\n", lvl, this); - for (int i=0; iprintf(" %3d: %016lx -> Level %d table at %016lx\n", - i, ent, deeper(lvl), (ent & ~0xfffull) + page_offset); + i, ent, deeper(lvl), (ent & ~0xfffull) + linear_offset); } if (lvl != level::pt && recurse) { - for (int i=0; i<=memory::table_entries; ++i) { + for (int i=0; i<=arch::table_entries; ++i) { if (is_large_page(lvl, i)) continue; diff --git a/src/kernel/page_table.h b/src/kernel/page_table.h index fec0077..ac0e7c1 100644 --- a/src/kernel/page_table.h +++ b/src/kernel/page_table.h @@ -3,9 +3,9 @@ /// Helper structures for dealing with page tables. #include +#include #include #include -#include struct free_page_header; @@ -173,7 +173,7 @@ struct page_table /// 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[arch::table_entries]; }; diff --git a/src/kernel/page_tree.cpp b/src/kernel/page_tree.cpp index b2e0cd6..3e37359 100644 --- a/src/kernel/page_tree.cpp +++ b/src/kernel/page_tree.cpp @@ -1,8 +1,9 @@ #include +#include + #include "assert.h" #include "frame_allocator.h" -#include "kernel_memory.h" #include "page_tree.h" // Page tree levels map the following parts of an offset. Note the xxx part of @@ -26,7 +27,7 @@ static_assert(sizeof(page_tree) == 66 * sizeof(uintptr_t)); static constexpr unsigned max_level = 5; static constexpr unsigned bits_per_level = 6; -inline int level_shift(uint8_t level) { return level * bits_per_level + memory::frame_bits; } +inline int level_shift(uint8_t level) { return level * bits_per_level + arch::frame_bits; } inline uint64_t level_mask(uint8_t level) { return ~0x3full << level_shift(level); } inline int index_for(uint64_t off, uint8_t level) { return (off >> level_shift(level)) & 0x3full; } diff --git a/src/kernel/panic.serial/symbol_table.cpp b/src/kernel/panic.serial/symbol_table.cpp index ff22abe..3f0c288 100644 --- a/src/kernel/panic.serial/symbol_table.cpp +++ b/src/kernel/panic.serial/symbol_table.cpp @@ -1,4 +1,3 @@ -#include "pointer_manipulation.h" #include "symbol_table.h" namespace panicking { diff --git a/src/kernel/panic.serial/symbol_table.h b/src/kernel/panic.serial/symbol_table.h index 98d8b58..6b7be3e 100644 --- a/src/kernel/panic.serial/symbol_table.h +++ b/src/kernel/panic.serial/symbol_table.h @@ -1,7 +1,7 @@ #pragma once #include -#include "counted.h" +#include namespace panicking { @@ -26,7 +26,7 @@ private: }; const void *m_data; - counted m_entries; + util::counted m_entries; }; } // namespace panicking diff --git a/src/kernel/pci.cpp b/src/kernel/pci.cpp index ab37c38..964dbc0 100644 --- a/src/kernel/pci.cpp +++ b/src/kernel/pci.cpp @@ -106,7 +106,7 @@ pci_device::pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t fu // Walk the extended capabilities list uint8_t next = m_base[13] & 0xff; while (next) { - pci_cap *cap = reinterpret_cast(offset_pointer(m_base, next)); + pci_cap *cap = reinterpret_cast(util::offset_pointer(m_base, next)); next = cap->next; log::debug(logs::device, " - found PCI cap type %02x", cap->id); diff --git a/src/kernel/pci.h b/src/kernel/pci.h index 1e446e3..08d59ec 100644 --- a/src/kernel/pci.h +++ b/src/kernel/pci.h @@ -3,7 +3,7 @@ /// PCI devices and groups #include -#include "memory.h" +#include struct pci_group; enum class isr : uint8_t; @@ -126,7 +126,7 @@ struct pci_group /// \returns A pointer to the memory-mapped configuration registers inline uint32_t * base_for(uint8_t bus, uint8_t device, uint8_t func) { - return offset_pointer(base, + return util::offset_pointer(base, pci_device::bus_addr(bus, device, func) << 12); } diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index b900f27..ec3638b 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -13,7 +13,6 @@ #include "gdt.h" #include "interrupts.h" #include "io.h" -#include "kernel_memory.h" #include "log.h" #include "msr.h" #include "objects/channel.h" diff --git a/src/kernel/syscalls/system.cpp b/src/kernel/syscalls/system.cpp index ded323d..60cfbf5 100644 --- a/src/kernel/syscalls/system.cpp +++ b/src/kernel/syscalls/system.cpp @@ -5,6 +5,7 @@ #include "device_manager.h" #include "frame_allocator.h" #include "log.h" +#include "memory.h" #include "objects/endpoint.h" #include "objects/thread.h" #include "objects/system.h" @@ -70,7 +71,7 @@ system_map_phys(j6_handle_t handle, j6_handle_t * area, uintptr_t phys, size_t s // 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, memory::page_count(size)); + frame_allocator::get().used(phys, mem::page_count(size)); vm_flags vmf = (static_cast(flags) & vm_flags::driver_mask); construct_handle(area, phys, size, vmf); diff --git a/src/kernel/tss.cpp b/src/kernel/tss.cpp index bc711b4..d472ebf 100644 --- a/src/kernel/tss.cpp +++ b/src/kernel/tss.cpp @@ -3,8 +3,8 @@ #include "assert.h" #include "cpu.h" -#include "kernel_memory.h" #include "log.h" +#include "memory.h" #include "objects/vm_area.h" #include "tss.h" @@ -45,8 +45,8 @@ 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; + using mem::frame_size; + using mem::kernel_stack_pages; constexpr size_t stack_bytes = kernel_stack_pages * frame_size; for (unsigned ist = 1; ist < 8; ++ist) { diff --git a/src/kernel/vm_space.cpp b/src/kernel/vm_space.cpp index a1908a3..76f0cdb 100644 --- a/src/kernel/vm_space.cpp +++ b/src/kernel/vm_space.cpp @@ -1,10 +1,11 @@ #include -#include "kernel_memory.h" +#include #include "assert.h" #include "frame_allocator.h" #include "log.h" +#include "memory.h" #include "objects/process.h" #include "objects/thread.h" #include "objects/vm_area.h" @@ -42,8 +43,8 @@ vm_space::vm_space() : m_pml4 = page_table::get_table_page(); page_table *kpml4 = kernel_space().m_pml4; - memset(m_pml4, 0, memory::frame_size/2); - for (unsigned i = memory::pml4e_kernel; i < memory::table_entries; ++i) + memset(m_pml4, 0, mem::frame_size/2); + for (unsigned i = arch::kernel_root_index; i < arch::table_entries; ++i) m_pml4->entries[i] = kpml4->entries[i]; } @@ -81,7 +82,7 @@ void vm_space::remove_area(vm_area *area) { area->remove_from(this); - clear(*area, 0, memory::page_count(area->size())); + clear(*area, 0, mem::page_count(area->size())); area->handle_release(); } @@ -153,7 +154,7 @@ vm_space::copy_from(const vm_space &source, const vm_area &vma) if (!find_vma(vma, from) || !source.find_vma(vma, from)) return; - size_t count = memory::page_count(vma.size()); + size_t count = mem::page_count(vma.size()); page_table::iterator dit {to, m_pml4}; page_table::iterator sit {from, source.m_pml4}; @@ -169,7 +170,7 @@ vm_space::copy_from(const vm_space &source, const vm_area &vma) void vm_space::page_in(const vm_area &vma, uintptr_t offset, uintptr_t phys, size_t count) { - using memory::frame_size; + using mem::frame_size; util::scoped_lock lock {m_lock}; uintptr_t base = 0; @@ -197,7 +198,7 @@ vm_space::page_in(const vm_area &vma, uintptr_t offset, uintptr_t phys, size_t c void vm_space::clear(const vm_area &vma, uintptr_t offset, size_t count, bool free) { - using memory::frame_size; + using mem::frame_size; util::scoped_lock lock {m_lock}; uintptr_t base = 0; @@ -248,13 +249,13 @@ vm_space::active() const { uintptr_t pml4 = 0; __asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (pml4) ); - return memory::to_virtual(pml4 & ~0xfffull) == m_pml4; + return mem::to_virtual(pml4 & ~0xfffull) == m_pml4; } void vm_space::activate() const { - constexpr uint64_t phys_mask = ~memory::page_offset & ~0xfffull; + constexpr uint64_t phys_mask = ~mem::linear_offset & ~0xfffull; uintptr_t p = reinterpret_cast(m_pml4) & phys_mask; __asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (p) ); } @@ -264,7 +265,7 @@ vm_space::initialize_tcb(TCB &tcb) { tcb.pml4 = reinterpret_cast(m_pml4) & - ~memory::page_offset; + ~mem::linear_offset; } bool @@ -300,8 +301,8 @@ vm_space::copy(vm_space &source, vm_space &dest, const void *from, void *to, siz // TODO: iterate page mappings and continue copying. For now i'm blindly // assuming both buffers are fully contained within single pages memcpy( - memory::to_virtual((*dit & ~0xfffull) | (ito & 0xffful)), - memory::to_virtual((*sit & ~0xfffull) | (ifrom & 0xffful)), + mem::to_virtual((*dit & ~0xfffull) | (ito & 0xffful)), + mem::to_virtual((*sit & ~0xfffull) | (ifrom & 0xffful)), length); return length; diff --git a/src/libraries/bootproto/bootproto.module b/src/libraries/bootproto/bootproto.module new file mode 100644 index 0000000..5d6a4ab --- /dev/null +++ b/src/libraries/bootproto/bootproto.module @@ -0,0 +1,12 @@ +# vim: ft=python + +bp = module("bootproto", + kind = "lib", + includes = [ "include" ], + sources = [ + ]) + +from os.path import join + +layout = join(source_root, "definitions/memory_layout.csv") +bp.add_input("include/bootproto/memory.h.cog", deps=[layout]) diff --git a/src/include/init_args.h b/src/libraries/bootproto/include/bootproto/init.h similarity index 84% rename from src/include/init_args.h rename to src/libraries/bootproto/include/bootproto/init.h index fe6ffd4..af0dedd 100644 --- a/src/include/init_args.h +++ b/src/libraries/bootproto/include/bootproto/init.h @@ -1,12 +1,13 @@ #pragma once +/// \file bootproto/init.h +/// Data structures for initializing the init server #include #include -#include "counted.h" +#include -namespace kernel { -namespace init { +namespace bootproto { enum class module_type : uint8_t { none, @@ -52,7 +53,7 @@ struct video_mode struct module_framebuffer : public module { - buffer framebuffer; + util::buffer framebuffer; video_mode mode; fb_type type; }; @@ -64,5 +65,4 @@ struct modules_page uintptr_t next; }; -} // namespace init -} // namespace kernel +} // namespace bootproto diff --git a/src/include/kernel_args.h b/src/libraries/bootproto/include/bootproto/kernel.h similarity index 85% rename from src/include/kernel_args.h rename to src/libraries/bootproto/include/bootproto/kernel.h index 1b30b43..060a8df 100644 --- a/src/include/kernel_args.h +++ b/src/libraries/bootproto/include/bootproto/kernel.h @@ -1,14 +1,16 @@ #pragma once +/// \file bootproto/kernel.h +/// Data structures for initializing the kernel #include #include #include -#include "counted.h" -namespace kernel { -namespace init { +#include -constexpr uint32_t args_magic = 'j6ia'; // "jsix init args" +namespace bootproto { + +constexpr uint32_t args_magic = 'j6bp'; // "jsix boot protocol" constexpr uint16_t args_version = 1; constexpr uint64_t header_magic = 0x4c454e52454b366aull; // 'j6KERNEL' @@ -32,7 +34,7 @@ struct program_section { struct program { uintptr_t entrypoint; uintptr_t phys_base; - counted sections; + util::counted sections; }; enum class mem_type : uint32_t { @@ -120,9 +122,9 @@ struct args boot_flags flags; void *pml4; - counted page_tables; - counted mem_map; - counted frame_blocks; + util::counted page_tables; + util::counted mem_map; + util::counted frame_blocks; program *kernel; program *init; @@ -153,7 +155,6 @@ struct header uint64_t flags; }; -using entrypoint = __attribute__((sysv_abi)) void (*)(init::args *); +using entrypoint = __attribute__((sysv_abi)) void (*)(args *); -} // namespace init -} // namespace kernel +} // namespace bootproto diff --git a/src/libraries/bootproto/include/bootproto/memory.h.cog b/src/libraries/bootproto/include/bootproto/memory.h.cog new file mode 100644 index 0000000..fa9b590 --- /dev/null +++ b/src/libraries/bootproto/include/bootproto/memory.h.cog @@ -0,0 +1,24 @@ +#pragma once +// vim: ft=cpp + +/// \file bootproto/memory.h +/// Import memory layout constants necessary for boot + +namespace bootproto { +namespace mem { + +/*[[[cog code generation +from os.path import join +from memory import Layout + +layout = Layout(join(definitions_path, "memory_layout.csv")) + +for region in layout.regions: + if region.shared: + cog.outl(f"constexpr uintptr_t {region.name}_offset = 0x{region.start:x};") + +]]]*/ +///[[[end]]] + +} // namespace mem +} // namespace bootproto diff --git a/src/libraries/elf/elf.module b/src/libraries/elf/elf.module index a6a6bd3..77ce5c3 100644 --- a/src/libraries/elf/elf.module +++ b/src/libraries/elf/elf.module @@ -3,6 +3,7 @@ module("elf", kind = "lib", includes = [ "include" ], + deps = [ "util" ], sources = [ "file.cpp", ]) diff --git a/src/libraries/elf/file.cpp b/src/libraries/elf/file.cpp index 2aa2870..2ccb641 100644 --- a/src/libraries/elf/file.cpp +++ b/src/libraries/elf/file.cpp @@ -1,6 +1,5 @@ -#include "elf/file.h" -#include "elf/headers.h" -#include "pointer_manipulation.h" +#include +#include static const uint32_t expected_magic = 0x464c457f; // "\x7f" "ELF" @@ -8,9 +7,14 @@ namespace elf { inline const file_header * fh(const void *data) { return reinterpret_cast(data); } +template +const T *convert(const void *data, size_t offset) { + return reinterpret_cast(util::offset_pointer(data, offset)); +} + 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_programs(convert(data, fh(data)->ph_offset), fh(data)->ph_entsize, fh(data)->ph_num), + m_sections(convert(data, fh(data)->sh_offset), fh(data)->sh_entsize, fh(data)->sh_num), m_data(data), m_size(size) { diff --git a/src/libraries/elf/include/elf/file.h b/src/libraries/elf/include/elf/file.h index 87957a8..6ce72d1 100644 --- a/src/libraries/elf/include/elf/file.h +++ b/src/libraries/elf/include/elf/file.h @@ -2,7 +2,7 @@ #include #include -#include "pointer_manipulation.h" +#include namespace elf { @@ -14,7 +14,7 @@ template class subheaders { public: - using iterator = const_offset_iterator; + using iterator = util::const_offset_iterator; subheaders(const T *start, size_t size, unsigned count) : m_start(start), m_size(size), m_count(count) {} @@ -22,9 +22,9 @@ public: 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 T & operator [] (int i) const { return *util::offset_pointer(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 iterator end() const { return util::offset_pointer(m_start, m_size*m_count); } private: const T *m_start; diff --git a/src/include/counted.h b/src/libraries/util/include/util/counted.h similarity index 83% rename from src/include/counted.h rename to src/libraries/util/include/util/counted.h index 2a5e460..dd93d5e 100644 --- a/src/include/counted.h +++ b/src/libraries/util/include/util/counted.h @@ -2,7 +2,9 @@ /// \file counted.h /// Definition of the `counted` template class -#include "pointer_manipulation.h" +#include + +namespace util { /// A pointer and an associated count. Memory pointed to is not managed. /// Depending on the usage, the count may be size or number of elements. @@ -26,13 +28,13 @@ struct counted 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); } + inline iterator end() { return offset_pointer(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 end of the array - inline const_iterator end() const { return offset_ptr(pointer, sizeof(T)*count); } + inline const_iterator end() const { return offset_pointer(pointer, sizeof(T)*count); } }; /// Specialize for `void` which cannot be indexed or iterated @@ -44,3 +46,5 @@ struct counted }; using buffer = counted; + +} // namespace util diff --git a/src/libraries/util/include/util/misc.h b/src/libraries/util/include/util/misc.h index 3e2fe63..ada1c29 100644 --- a/src/libraries/util/include/util/misc.h +++ b/src/libraries/util/include/util/misc.h @@ -2,11 +2,23 @@ namespace util { +/// Reverse the order of bytes in a 32 bit integer constexpr uint32_t -byteswap(uint32_t x) -{ +byteswap32(uint32_t x) { return ((x >> 24) & 0x000000ff) | ((x >> 8) & 0x0000ff00) | ((x << 8) & 0x00ff0000) | ((x << 24) & 0xff000000); } +/// Do a simple byte-wise checksum of an area of memory. The area +/// summed will be the bytes at indicies [off, len). +/// \arg p The start of the memory region +/// \arg len The number of bytes in the region +/// \arg off An optional offset into the region +uint8_t checksum(const void *p, size_t len, size_t off = 0) { + uint8_t sum = 0; + const uint8_t *c = reinterpret_cast(p); + for (size_t i = off; i < len; ++i) sum += c[i]; + return sum; +} + } diff --git a/src/include/pointer_manipulation.h b/src/libraries/util/include/util/pointers.h similarity index 70% rename from src/include/pointer_manipulation.h rename to src/libraries/util/include/util/pointers.h index bc9c657..99d3d00 100644 --- a/src/include/pointer_manipulation.h +++ b/src/libraries/util/include/util/pointers.h @@ -1,17 +1,37 @@ -/// \file pointer_manipulation.h +/// \file pointers.h /// Helper functions and types for doing type-safe byte-wise pointer math. #pragma once +#include #include +namespace util { + /// Return a pointer offset from `input` by `offset` bytes. -/// \tparam T Cast the return value to a pointer to `T` -/// \tparam S The type pointed to by the `input` pointer -template -inline T* offset_ptr(S* input, ptrdiff_t offset) { +/// \arg input The original pointer +/// \arg offset Offset `input` by this many bytes +template +inline T* offset_pointer(T* input, ptrdiff_t offset) { return reinterpret_cast(reinterpret_cast(input) + offset); } +/// Return a pointer with the given bits masked out +/// \arg input The original pointer +/// \arg mask A bitmask of bits to clear from p +/// \returns The masked pointer +template +inline T* mask_pointer(T *input, uintptr_t mask) { + return reinterpret_cast(reinterpret_cast(input) & ~mask); +} + +/// Read a value of type T from a location in memory +/// \arg p The location in memory to read +/// \returns The value at the given location cast to T +template +inline T read_from(const void *p) { + return *reinterpret_cast(p); +} + /// Iterator for an array of `const T` whose size is known at runtime /// \tparam T Type of the objects in the array, whose size might not be /// what is returned by sizeof(T). @@ -25,7 +45,7 @@ public: /// 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++() { m_t = offset_pointer(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; } @@ -55,7 +75,7 @@ public: /// 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++() { m_t = offset_pointer(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; } @@ -72,3 +92,4 @@ private: size_t m_off; }; +} // namespace util diff --git a/src/user/srv.init/init.module b/src/user/srv.init/init.module index d03214c..29df789 100644 --- a/src/user/srv.init/init.module +++ b/src/user/srv.init/init.module @@ -2,7 +2,7 @@ init = module("srv.init", targets = [ "user" ], - deps = [ "libc", "elf" ], + deps = [ "libc", "elf", "bootproto" ], sources = [ "loader.cpp", "main.cpp", diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index e5d40dc..7a2c8ff 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -1,16 +1,16 @@ #include #include +#include #include #include #include #include #include -#include #include -using kernel::init::module_flags; -using kernel::init::module_program; +using bootproto::module_flags; +using bootproto::module_program; extern j6_handle_t handle_self; extern j6_handle_t handle_system; diff --git a/src/user/srv.init/loader.h b/src/user/srv.init/loader.h index 89dc35c..fd32403 100644 --- a/src/user/srv.init/loader.h +++ b/src/user/srv.init/loader.h @@ -2,9 +2,8 @@ /// \file loader.h /// Routines for loading and starting other programs -namespace kernel { -namespace init { +namespace bootproto { struct module_program; -}} +} -bool load_program(const kernel::init::module_program &prog, char *err_msg); +bool load_program(const bootproto::module_program &prog, char *err_msg); diff --git a/src/user/srv.init/main.cpp b/src/user/srv.init/main.cpp index 7cb1635..893857e 100644 --- a/src/user/srv.init/main.cpp +++ b/src/user/srv.init/main.cpp @@ -1,14 +1,14 @@ #include #include -#include +#include #include "loader.h" #include "modules.h" -using kernel::init::module; -using kernel::init::module_type; -using kernel::init::module_program; +using bootproto::module; +using bootproto::module_type; +using bootproto::module_program; extern "C" { int main(int, const char **); diff --git a/src/user/srv.init/modules.cpp b/src/user/srv.init/modules.cpp index e5c8873..137c41f 100644 --- a/src/user/srv.init/modules.cpp +++ b/src/user/srv.init/modules.cpp @@ -6,8 +6,8 @@ #include "modules.h" -using module = kernel::init::module; -using modules_page = kernel::init::modules_page; +using module = bootproto::module; +using modules_page = bootproto::modules_page; static const modules_page * get_page(const module *mod) @@ -20,7 +20,7 @@ const module * module_iterator::operator++() { do { - m_mod = offset_ptr(m_mod, m_mod->mod_length); + m_mod = util::offset_pointer(m_mod, m_mod->mod_length); if (m_mod->mod_type == type::none) { // We've reached the end of a page, see if there's another diff --git a/src/user/srv.init/modules.h b/src/user/srv.init/modules.h index 62c4ea0..3e160fe 100644 --- a/src/user/srv.init/modules.h +++ b/src/user/srv.init/modules.h @@ -2,16 +2,16 @@ /// \file modules.h /// Routines for loading initial argument modules +#include #include -#include -#include +#include class module_iterator { public: - using type = kernel::init::module_type; - using module = kernel::init::module; + using type = bootproto::module_type; + using module = bootproto::module; module_iterator(const module *m, type t = type::none) : m_mod {m}, m_type {t} {} @@ -40,7 +40,7 @@ private: class modules { public: - using type = kernel::init::module_type; + using type = bootproto::module_type; using iterator = module_iterator; static modules load_modules( @@ -54,7 +54,7 @@ public: iterator end() const { return nullptr; } private: - using module = kernel::init::module; + using module = bootproto::module; modules(const module* root) : m_root {root} {}