From 9f54927a82a644b80adde4baf6c09bdccb504a56 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sun, 25 Feb 2024 23:40:14 -0800 Subject: [PATCH] [util] Remove enum_bitfields The enum_bitfields system never worked quite right, and always had edge cases where name resolution for the SFINAE would fail. Move everything over to use util::bitset, which can be constexpr and boils down to inline integer bitops in release mode. Improved util::bitset itself, moving the array-backed base implementation into a new util::sized_bitset, and making the single-inttype backed implementation the base case. Also added a distinction between | or |= (which work with real bit values) and + or += (which work with bit indexes). --- src/boot/bootconfig.cpp | 2 +- src/boot/bootconfig.h | 7 +- src/boot/loader.cpp | 8 +- src/boot/main.cpp | 7 +- src/include/arch/acpi/tables.h | 51 ++- src/kernel/apic.cpp | 8 +- src/kernel/apic.h | 32 +- src/kernel/cpu.cpp | 5 +- src/kernel/gdt.cpp | 29 +- src/kernel/gdt.h | 27 +- src/kernel/interrupts.cpp | 3 +- src/kernel/kernel_main.cpp | 13 +- src/kernel/memory_bootstrap.cpp | 27 +- src/kernel/objects/thread.h | 1 - src/kernel/objects/vm_area.cpp | 14 +- src/kernel/objects/vm_area.h | 25 +- src/kernel/page_table.cpp | 9 +- src/kernel/page_table.h | 58 +-- src/kernel/scheduler.cpp | 2 +- src/kernel/smp.cpp | 11 +- src/kernel/syscalls/system.cpp | 7 +- src/kernel/syscalls/vm_area.cpp | 10 +- src/kernel/vm_space.cpp | 38 +- src/kernel/vm_space.h | 21 +- .../bootproto/include/bootproto/bootconfig.h | 8 +- .../bootproto/include/bootproto/kernel.h | 21 +- src/libraries/cpu/include/cpu/cpu_id.h | 2 +- src/libraries/elf/include/elf/headers.h | 24 +- src/libraries/j6/include/j6/flags.h | 3 +- .../j6/include/j6/tables/vm_flags.inc | 20 +- src/libraries/util/include/util/bitset.h | 376 ++++++------------ .../util/include/util/enum_bitfields.h | 99 ----- src/libraries/util/util.module | 1 - src/user/ld.so/image.cpp | 2 +- src/user/srv.init/j6romfs.h | 1 - src/user/srv.init/loader.cpp | 2 +- 36 files changed, 352 insertions(+), 622 deletions(-) delete mode 100644 src/libraries/util/include/util/enum_bitfields.h diff --git a/src/boot/bootconfig.cpp b/src/boot/bootconfig.cpp index 9dfa58e..cd9a495 100644 --- a/src/boot/bootconfig.cpp +++ b/src/boot/bootconfig.cpp @@ -22,7 +22,7 @@ read_string(util::buffer &data) static void read_descriptor(descriptor &e, util::buffer &data) { - e.flags = static_cast(*util::read(data)); + e.flags = util::bitset16 {*util::read(data)}; e.path = read_string(data); } diff --git a/src/boot/bootconfig.h b/src/boot/bootconfig.h index 1220b8d..189f38a 100644 --- a/src/boot/bootconfig.h +++ b/src/boot/bootconfig.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include namespace uefi { @@ -14,7 +15,7 @@ namespace boot { using desc_flags = bootproto::desc_flags; struct descriptor { - desc_flags flags; + util::bitset16 flags; wchar_t const *path; }; @@ -27,7 +28,7 @@ public: /// Constructor. Loads bootconfig from the given buffer. bootconfig(util::buffer data, uefi::boot_services *bs); - inline uint16_t flags() const { return m_flags; } + inline util::bitset16 flags() const { return m_flags; } inline const descriptor & kernel() const { return m_kernel; } inline const descriptor & init() const { return m_init; } inline const wchar_t * initrd() const { return m_initrd; } @@ -35,7 +36,7 @@ public: inline const descriptors & panics() { return m_panics; } private: - uint16_t m_flags; + util::bitset16 m_flags; descriptor m_kernel; descriptor m_init; descriptors m_panics; diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index 3f1853e..1fccb2a 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -110,7 +110,7 @@ parse_program(const wchar_t *name, util::const_buffer data, bootproto::program & section.phys_addr = elf.base() + seg.offset; section.virt_addr = seg.vaddr; section.size = seg.mem_size; - section.type = static_cast(seg.flags); + section.type = seg.flags; if (seg.mem_size != seg.file_size) section.phys_addr = allocate_bss(seg); @@ -128,8 +128,6 @@ load_program( paging::pager &pager, bool verify) { - using util::bits::has; - status_line status(L"Loading program", name); elf::file elf {data}; @@ -155,8 +153,8 @@ load_program( pager.map_pages(phys_addr, seg.vaddr, memory::bytes_to_pages(seg.mem_size), - has(seg.flags, elf::segment_flags::write), - has(seg.flags, elf::segment_flags::exec)); + seg.flags.get(elf::segment_flags::write), + seg.flags.get(elf::segment_flags::exec)); } return elf.entrypoint(); diff --git a/src/boot/main.cpp b/src/boot/main.cpp index df04539..d53a882 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -82,9 +82,8 @@ load_resources( util::buffer kernel = loader::load_file(disk, bc.kernel().path); uintptr_t kentry = loader::load_program(kernel, L"jsix kernel", pager, true); - args->flags = static_cast(bc.flags()); + args->flags = bc.flags(); - namespace bits = util::bits; using bootproto::desc_flags; bool has_panic = false; @@ -96,7 +95,7 @@ load_resources( // Find the screen-specific panic handler first to // give it priority for (const descriptor &d : bc.panics()) { - if (bits::has(d.flags, desc_flags::graphical)) { + if (d.flags.get(desc_flags::graphical)) { panic = loader::load_file(disk, d.path); has_panic = true; break; @@ -106,7 +105,7 @@ load_resources( if (!has_panic) { for (const descriptor &d : bc.panics()) { - if (!bits::has(d.flags, desc_flags::graphical)) { + if (d.flags.get(desc_flags::graphical)) { panic = loader::load_file(disk, d.path); has_panic = true; break; diff --git a/src/include/arch/acpi/tables.h b/src/include/arch/acpi/tables.h index d7bf536..0889a9e 100644 --- a/src/include/arch/acpi/tables.h +++ b/src/include/arch/acpi/tables.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include // for byteswap32 namespace acpi { @@ -62,32 +62,31 @@ struct gas } __attribute__ ((packed)); -enum class fadt_flags : uint32_t +enum class fadt_flags { - 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, + wbinvd_flush, + proc_c1, + p_lvl2_up, + pwr_button, + slp_button, + fix_rtc, + rtc_s4, + tmr_val_ext, + dck_cap, + reset_reg_sup, + sealed_case, + headless, + cpu_sw_slp, + pci_exp_wak, + use_plat_clock, + s4_rtc_sts_val, + remote_pwr_cap, + apic_cluster, + apic_physical, + hw_reduced_acpi, + low_pwr_s0_idle }; -is_bitfield(fadt_flags); struct fadt { @@ -134,7 +133,7 @@ struct fadt uint16_t iapc_boot_arch; uint8_t reserved1; - fadt_flags flags; + util::bitset32 flags; gas reset_reg; uint8_t reset_value; diff --git a/src/kernel/apic.cpp b/src/kernel/apic.cpp index ac46817..1925145 100644 --- a/src/kernel/apic.cpp +++ b/src/kernel/apic.cpp @@ -71,21 +71,19 @@ lapic::get_id() } void -lapic::send_ipi(ipi mode, isr vector, uint8_t dest) +lapic::send_ipi(util::bitset32 mode, isr vector, uint8_t dest) { // Wait until the APIC is ready to send ipi_wait(); - uint32_t command = - static_cast(vector) | - static_cast(mode); + uint32_t command = util::bitset32::from(vector) | mode; 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, isr vector) +lapic::send_ipi_broadcast(util::bitset32 mode, bool self, isr vector) { // Wait until the APIC is ready to send ipi_wait(); diff --git a/src/kernel/apic.h b/src/kernel/apic.h index aee838a..83eb2ad 100644 --- a/src/kernel/apic.h +++ b/src/kernel/apic.h @@ -3,7 +3,7 @@ /// Classes to control both local and I/O APICs. #include -#include +#include #include "interrupts.h" @@ -33,33 +33,30 @@ public: /// Get the local APIC's ID uint8_t get_id(); - enum class ipi : uint32_t + enum class ipi_flags { - // 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 + logical = 11, + pending = 12, + assert = 14, + level = 15, }; + // IPI flags based on delivery mode (bits 8-10) + static constexpr util::bitset32 ipi_fixed = 0; + static constexpr util::bitset32 ipi_init = 0x500; + static constexpr util::bitset32 ipi_sipi = 0x600; + /// 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, isr vector, uint8_t dest); + void send_ipi(util::bitset32 mode, isr 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, isr vector); + void send_ipi_broadcast(util::bitset32 mode, bool self, isr vector); /// Wait for an IPI to finish sending. This is done automatically /// before sending another IPI with send_ipi(). @@ -145,6 +142,3 @@ private: uint8_t m_id; uint8_t m_version; }; - -is_bitfield(lapic::ipi); - diff --git a/src/kernel/cpu.cpp b/src/kernel/cpu.cpp index 21c631c..a6bb001 100644 --- a/src/kernel/cpu.cpp +++ b/src/kernel/cpu.cpp @@ -118,7 +118,7 @@ cpu_early_init(cpu_data *cpu) set_xcr0(xcr0_val); // Set initial floating point state - const util::bitset32 mxcsr_val { + const util::bitset32 mxcsr_val = util::bitset32::of( mxcsr::DAZ, mxcsr::IM, mxcsr::DM, @@ -126,8 +126,7 @@ cpu_early_init(cpu_data *cpu) mxcsr::OM, mxcsr::UM, mxcsr::PM, - mxcsr::FTZ, - }; + mxcsr::FTZ); asm ( "ldmxcsr %0" :: "m"(mxcsr_val) ); // Install the GS base pointint to the cpu_data diff --git a/src/kernel/gdt.cpp b/src/kernel/gdt.cpp index 179a014..f38067b 100644 --- a/src/kernel/gdt.cpp +++ b/src/kernel/gdt.cpp @@ -22,6 +22,9 @@ static constexpr uint8_t tss_index = 6; // Note that this takes TWO GDT en static util::no_construct __g_bsp_gdt_storage; GDT &g_bsp_gdt = __g_bsp_gdt_storage.value; +static constexpr util::bitset8 ring3 = util::bitset8::of( GDT::type::ring1, GDT::type::ring2 ); +static constexpr util::bitset8 rw = util::bitset8::of( GDT::type::read_write ); +static constexpr util::bitset8 rwx = util::bitset8::of( GDT::type::read_write, GDT::type::execute ); GDT::GDT(TSS *tss) : m_tss(tss) @@ -32,13 +35,13 @@ GDT::GDT(TSS *tss) : 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); + set(kern_cs_index, 0, 0xfffff, true, rwx); + set(kern_ss_index, 0, 0xfffff, true, rw); // 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(user_cs32_index, 0, 0xfffff, false, ring3 | rwx); + set(user_ss_index, 0, 0xfffff, true, ring3 | rw); + set(user_cs64_index, 0, 0xfffff, true, ring3 | rwx); set_tss(tss); } @@ -61,7 +64,7 @@ GDT::install() const } void -GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t) +GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, util::bitset8 t) { m_entries[i].limit_low = limit & 0xffff; m_entries[i].size = (limit >> 16) & 0xf; @@ -71,7 +74,9 @@ GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t) 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; + static constexpr util::bitset8 sp = util::bitset8::of( type::system, type::present ); + m_entries[i].type = t; + m_entries[i].type |= sp; } struct tss_descriptor @@ -79,7 +84,7 @@ struct tss_descriptor uint16_t limit_low; uint16_t base_00; uint8_t base_16; - GDT::type type; + util::bitset8 type; uint8_t size; uint8_t base_24; uint32_t base_32; @@ -102,11 +107,9 @@ GDT::set_tss(TSS *tss) tssd.base_32 = (base >> 32) & 0xffffffff; tssd.reserved = 0; - tssd.type = - type::accessed | - type::execute | - type::ring3 | - type::present; + static constexpr util::bitset8 tss_mark = + util::bitset8::of(type::accessed, type::execute, type::present); + tssd.type = ring3 | tss_mark; memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor)); } diff --git a/src/kernel/gdt.h b/src/kernel/gdt.h index ffce36f..312f1e8 100644 --- a/src/kernel/gdt.h +++ b/src/kernel/gdt.h @@ -3,7 +3,7 @@ /// Definitions relating to a CPU's GDT table #include -#include +#include class TSS; @@ -25,21 +25,20 @@ public: /// \arg index Which entry to print, or -1 for all entries void dump(unsigned index = -1) const; - enum class type : uint8_t + enum class type { - accessed = 0x01, - read_write = 0x02, - conforming = 0x04, - execute = 0x08, - system = 0x10, - ring1 = 0x20, - ring2 = 0x40, - ring3 = 0x60, - present = 0x80 + accessed, + read_write, + conforming, + execute, + system, + ring1, + ring2, + present }; private: - void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t); + void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, util::bitset8 t); void set_tss(TSS *tss); struct descriptor @@ -47,7 +46,7 @@ private: uint16_t limit_low; uint16_t base_low; uint8_t base_mid; - type type; + util::bitset8 type; uint8_t size; uint8_t base_high; } __attribute__ ((packed, align(8))); @@ -63,5 +62,3 @@ private: ptr m_ptr; }; - -is_bitfield(GDT::type); diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index fd95a7f..3b5e034 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -126,8 +126,7 @@ isr_handler(cpu_state *regs) // The zero page is always invalid if (cr2 > mem::frame_size) { bool user = cr2 < mem::kernel_offset; - vm_space::fault_type ft = - static_cast(regs->errorcode); + util::bitset8 ft = regs->errorcode; vm_space &space = user ? obj::process::current().space() diff --git a/src/kernel/kernel_main.cpp b/src/kernel/kernel_main.cpp index 97b4198..695723c 100644 --- a/src/kernel/kernel_main.cpp +++ b/src/kernel/kernel_main.cpp @@ -54,7 +54,7 @@ kernel_main(bootproto::args *args) bsp_late_init(); using bootproto::boot_flags; - bool enable_test = util::bits::has(args->flags, boot_flags::test); + bool enable_test = args->flags.get(boot_flags::test); syscall_initialize(enable_test); device_manager &devices = device_manager::get(); @@ -95,12 +95,15 @@ load_init_server(bootproto::program &program, uintptr_t modules_address) 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); + util::bitset32 flags = util::bitset32::of(vm_flags::exact); + if (sect.type.get(section_flags::execute)) + flags.set(vm_flags::exec); + + if (sect.type.get(section_flags::write)) + flags.set(vm_flags::write); obj::vm_area *vma = new obj::vm_area_fixed(sect.phys_addr, sect.size, flags); - space.add(sect.virt_addr, vma, obj::vm_flags::exact); + space.add(sect.virt_addr, vma, flags); } uint64_t iopl = (3ull << 12); diff --git a/src/kernel/memory_bootstrap.cpp b/src/kernel/memory_bootstrap.cpp index d596192..e4b8bde 100644 --- a/src/kernel/memory_bootstrap.cpp +++ b/src/kernel/memory_bootstrap.cpp @@ -20,7 +20,8 @@ extern "C" { using bootproto::allocation_register; -using obj::vm_flags; +inline constexpr util::bitset32 vm_flag_write = util::bitset32::of(obj::vm_flags::write); +inline constexpr util::bitset32 vm_flag_exact = util::bitset32::of(obj::vm_flags::exact); // These objects are initialized _before_ global constructors are called, // so we don't want them to have global constructors at all, lest they @@ -53,7 +54,7 @@ obj::vm_area_guarded g_kernel_buffers { mem::buffers_offset, mem::kernel_buffer_pages, mem::buffers_size, - vm_flags::write}; + vm_flag_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); } @@ -97,30 +98,30 @@ memory_initialize_pre_ctors(bootproto::args &kargs) // Create the heap space and heap allocator obj::vm_area *heap = new (&g_kernel_heap_area) - obj::vm_area_untracked(mem::heap_size, vm_flags::write); + obj::vm_area_untracked(mem::heap_size, vm_flag_write); obj::vm_area *heap_map = new (&g_kernel_heapmap_area) - obj::vm_area_untracked(mem::heapmap_size, vm_flags::write); + obj::vm_area_untracked(mem::heapmap_size, vm_flag_write); - vm.add(mem::heap_offset, heap, vm_flags::exact); - vm.add(mem::heapmap_offset, heap_map, vm_flags::exact); + vm.add(mem::heap_offset, heap, vm_flag_exact); + vm.add(mem::heapmap_offset, heap_map, vm_flag_exact); new (&g_kernel_heap) heap_allocator {mem::heap_offset, mem::heap_size, mem::heapmap_offset}; // Set up the log area and logger size_t log_buffer_size = log::log_pages * arch::frame_size; obj::vm_area *logs = new (&g_kernel_log_area) - obj::vm_area_ring(log_buffer_size, vm_flags::write); - vm.add(mem::logs_offset, logs, vm_flags::exact); + obj::vm_area_ring(log_buffer_size, vm_flag_write); + vm.add(mem::logs_offset, logs, vm_flag_exact); new (&g_logger) log::logger( util::buffer::from(mem::logs_offset, log_buffer_size)); // Set up the capability tables obj::vm_area *caps = new (&g_cap_table_area) - obj::vm_area_untracked(mem::caps_size, vm_flags::write); + obj::vm_area_untracked(mem::caps_size, vm_flag_write); - vm.add(mem::caps_offset, caps, vm_flags::exact); + vm.add(mem::caps_offset, caps, vm_flag_exact); new (&g_cap_table) cap_table {mem::caps_offset}; @@ -128,8 +129,8 @@ memory_initialize_pre_ctors(bootproto::args &kargs) mem::stacks_offset, mem::kernel_stack_pages, mem::stacks_size, - vm_flags::write}; - vm.add(mem::stacks_offset, &g_kernel_stacks, vm_flags::exact); + vm_flag_write}; + vm.add(mem::stacks_offset, &g_kernel_stacks, vm_flag_exact); // Clean out any remaning bootloader page table entries for (unsigned i = 0; i < arch::kernel_root_index; ++i) @@ -140,7 +141,7 @@ void memory_initialize_post_ctors(bootproto::args &kargs) { vm_space &vm = vm_space::kernel_space(); - vm.add(mem::buffers_offset, &g_kernel_buffers, vm_flags::exact); + vm.add(mem::buffers_offset, &g_kernel_buffers, vm_flag_exact); g_frame_allocator.free( get_physical_page(kargs.page_tables.pointer), diff --git a/src/kernel/objects/thread.h b/src/kernel/objects/thread.h index 0ddd968..e819eea 100644 --- a/src/kernel/objects/thread.h +++ b/src/kernel/objects/thread.h @@ -3,7 +3,6 @@ /// Definition of thread kobject types #include -#include #include #include diff --git a/src/kernel/objects/vm_area.cpp b/src/kernel/objects/vm_area.cpp index 8679fe6..4a7ef86 100644 --- a/src/kernel/objects/vm_area.cpp +++ b/src/kernel/objects/vm_area.cpp @@ -9,7 +9,7 @@ namespace obj { using mem::frame_size; -vm_area::vm_area(size_t size, vm_flags flags) : +vm_area::vm_area(size_t size, util::bitset32 flags) : m_size {size}, m_flags {flags}, m_spaces {m_vector_static, 0, static_size}, @@ -62,7 +62,7 @@ vm_area::can_resize(size_t size) return true; } -vm_area_fixed::vm_area_fixed(uintptr_t start, size_t size, vm_flags flags) : +vm_area_fixed::vm_area_fixed(uintptr_t start, size_t size, util::bitset32 flags) : m_start {start}, vm_area {size, flags} { @@ -70,7 +70,7 @@ vm_area_fixed::vm_area_fixed(uintptr_t start, size_t size, vm_flags flags) : vm_area_fixed::~vm_area_fixed() { - if (m_flags && vm_flags::mmio) + if (m_flags.get(vm_flags::mmio)) return; size_t pages = mem::page_count(m_size); @@ -94,7 +94,7 @@ vm_area_fixed::get_page(uintptr_t offset, uintptr_t &phys, bool alloc) return true; } -vm_area_untracked::vm_area_untracked(size_t size, vm_flags flags) : +vm_area_untracked::vm_area_untracked(size_t size, util::bitset32 flags) : vm_area {size, flags} { } @@ -127,7 +127,7 @@ vm_area_untracked::add_to(vm_space *space) } -vm_area_open::vm_area_open(size_t size, vm_flags flags) : +vm_area_open::vm_area_open(size_t size, util::bitset32 flags) : m_mapped {nullptr}, vm_area {size, flags} { @@ -154,7 +154,7 @@ vm_area_open::add_existing(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) : +vm_area_guarded::vm_area_guarded(uintptr_t start, size_t buf_pages, size_t size, util::bitset32 flags) : m_pages {buf_pages + 1}, // Sections are N+1 pages for the leading guard page m_stacks {start, m_pages*mem::frame_size}, vm_area_open {size, flags} @@ -191,7 +191,7 @@ vm_area_guarded::get_page(uintptr_t offset, uintptr_t &phys, bool alloc) return vm_area_open::get_page(offset, phys, alloc); } -vm_area_ring::vm_area_ring(size_t size, vm_flags flags) : +vm_area_ring::vm_area_ring(size_t size, util::bitset32 flags) : vm_area_open {size * 2, flags}, m_bufsize {size} { diff --git a/src/kernel/objects/vm_area.h b/src/kernel/objects/vm_area.h index 8b96889..457106c 100644 --- a/src/kernel/objects/vm_area.h +++ b/src/kernel/objects/vm_area.h @@ -6,8 +6,8 @@ #include #include +#include #include -#include #include "block_allocator.h" #include "objects/kobject.h" @@ -17,16 +17,15 @@ class vm_space; namespace obj { -enum class vm_flags : uint32_t +enum class vm_flags { #define VM_FLAG(name, v) name = v, #include #undef VM_FLAG - driver_mask = 0x00ff'ffff, ///< flags allowed via syscall for drivers - user_mask = 0x000f'ffff, ///< flags allowed via syscall for non-drivers }; -is_bitfield(vm_flags); +inline constexpr util::bitset32 vm_driver_mask = 0x00ff'ffff; ///< flags allowed via syscall for drivers +inline constexpr util::bitset32 vm_user_mask = 0x000f'ffff; ///< flags allowed via syscall for non-drivers /// Virtual memory areas allow control over memory allocation class vm_area : @@ -40,7 +39,7 @@ public: /// 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); + vm_area(size_t size, util::bitset32 flags = 0); virtual ~vm_area(); @@ -48,7 +47,7 @@ public: inline size_t size() const { return m_size; } /// Get the flags set for this area - inline vm_flags flags() const { return m_flags; } + inline util::bitset32 flags() const { return m_flags; } /// Track that this area was added to a vm_space /// \arg space The space to add this area to @@ -83,7 +82,7 @@ protected: bool can_resize(size_t size); size_t m_size; - vm_flags m_flags; + util::bitset32 m_flags; util::vector m_spaces; // Initial static space for m_spaces - most areas will never grow @@ -103,7 +102,7 @@ public: /// \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); + vm_area_fixed(uintptr_t start, size_t size, util::bitset32 flags = 0); virtual ~vm_area_fixed(); virtual size_t resize(size_t size) override; @@ -122,7 +121,7 @@ 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); + vm_area_open(size_t size, util::bitset32 flags); virtual ~vm_area_open(); virtual bool get_page(uintptr_t offset, uintptr_t &phys, bool alloc = true) override; @@ -144,7 +143,7 @@ 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); + vm_area_untracked(size_t size, util::bitset32 flags); virtual ~vm_area_untracked(); virtual bool add_to(vm_space *space) override; @@ -166,7 +165,7 @@ public: uintptr_t start, size_t sec_pages, size_t size, - vm_flags flags); + util::bitset32 flags); virtual ~vm_area_guarded(); @@ -194,7 +193,7 @@ public: /// \arg size Virtual size of the ring buffer. Note that /// the VMA size will be double this value. /// \arg flags Flags for this memory area - vm_area_ring(size_t size, vm_flags flags); + vm_area_ring(size_t size, util::bitset32 flags); virtual ~vm_area_ring(); virtual bool get_page(uintptr_t offset, uintptr_t &phys, bool alloc = true) override; diff --git a/src/kernel/page_table.cpp b/src/kernel/page_table.cpp index 8bd2290..86f74cb 100644 --- a/src/kernel/page_table.cpp +++ b/src/kernel/page_table.cpp @@ -14,10 +14,7 @@ free_page_header * page_table::s_page_cache = nullptr; util::spinlock page_table::s_lock; constexpr size_t page_table::entry_sizes[4]; - -constexpr page_table::flag table_flags = - page_table::flag::present | - page_table::flag::write; +inline constexpr util::bitset64 table_flags = page_flags::present | page_flags::write; page_table::iterator::iterator(uintptr_t virt, page_table *pml4) : @@ -140,9 +137,9 @@ page_table::iterator::ensure_table(level l) uintptr_t phys = reinterpret_cast(table) & ~linear_offset; uint64_t &parent = entry(l - 1); - flag flags = table_flags; + util::bitset64 flags = table_flags; if (m_index[0] < arch::kernel_root_index) - flags |= flag::user; + flags.set(flag::user); m_table[unsigned(l)] = table; parent = (phys & ~0xfffull) | flags; diff --git a/src/kernel/page_table.h b/src/kernel/page_table.h index 145e488..0ed2205 100644 --- a/src/kernel/page_table.h +++ b/src/kernel/page_table.h @@ -4,11 +4,33 @@ #include #include -#include +#include #include struct free_page_header; +namespace page_flags { + inline constexpr util::bitset64 none = 0x0000; + inline constexpr util::bitset64 present = 0x0001; /// Entry is present in the table + inline constexpr util::bitset64 write = 0x0002; /// Section may be written + inline constexpr util::bitset64 user = 0x0004; /// User-accessible + inline constexpr util::bitset64 pat0 = 0x0008; /// PAT selector bit 0 + inline constexpr util::bitset64 pat1 = 0x0010; /// PAT selector bit 1 + inline constexpr util::bitset64 accessed = 0x0020; /// Entry has been accessed + inline constexpr util::bitset64 dirty = 0x0040; /// Page has been written to + inline constexpr util::bitset64 page = 0x0080; /// Entry is a large page + inline constexpr util::bitset64 pat2 = 0x0080; /// PAT selector bit 2 on PT entries + inline constexpr util::bitset64 global = 0x0100; /// Entry is not PCID-specific + inline constexpr util::bitset64 pat2_lg = 0x1000; /// PAT selector bit 2 on large/huge pages + + inline constexpr util::bitset64 wb = 0; + inline constexpr util::bitset64 wt = pat0; + inline constexpr util::bitset64 uc_ = pat1; + inline constexpr util::bitset64 uc = pat0 | pat1; + inline constexpr util::bitset64 wc = pat0 | pat1 | pat2; + inline constexpr util::bitset64 wc_lg = pat0 | pat1 | pat2_lg; +} // page_flags + /// Struct to allow easy accessing of a memory page being used as a page table. struct page_table { @@ -16,27 +38,19 @@ struct page_table enum class level : unsigned { pml4, pdp, pd, pt, page }; /// Page entry flags - enum class flag : uint64_t + enum class flag { - 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, + present = 0, /// Entry is present in the table + write = 1, /// Section may be written + user = 2, /// User-accessible + pat0 = 3, /// PAT selector bit 0 + pat1 = 4, /// PAT selector bit 1 + accessed = 5, /// Entry has been accessed + dirty = 6, /// Page has been written to + page = 7, /// Entry is a large page + pat2 = 7, /// PAT selector bit 2 on PT entries + global = 8, /// Entry is not PCID-specific + pat2_lg = 12, /// PAT selector bit 2 on large/huge pages }; /// Helper for getting the next level value @@ -194,5 +208,3 @@ inline bool operator<(page_table::level a, page_table::level b) { inline page_table::level& operator++(page_table::level& l) { l = l + 1; return l; } inline page_table::level& operator--(page_table::level& l) { l = l - 1; return l; } - -is_bitfield(page_table::flag); diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index 20af63c..25561c6 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -339,5 +339,5 @@ scheduler::maybe_schedule(TCB *t) return; current_cpu().apic->send_ipi( - lapic::ipi::fixed, isr::ipiSchedule, cpu->id); + lapic::ipi_fixed, isr::ipiSchedule, cpu->id); } diff --git a/src/kernel/smp.cpp b/src/kernel/smp.cpp index edebcb6..3ac1605 100644 --- a/src/kernel/smp.cpp +++ b/src/kernel/smp.cpp @@ -57,8 +57,11 @@ start(cpu_data &bsp, void *kpml4) // Copy the startup code somwhere the real mode trampoline can run uintptr_t addr = 0x8000; // TODO: find a valid address, rewrite addresses isr vector = static_cast(addr >> 12); - obj::vm_area *vma = new obj::vm_area_fixed(addr, 0x1000, vm_flags::write); - vm_space::kernel_space().add(addr, vma, obj::vm_flags::exact); + + constexpr util::bitset32 flags = util::bitset32::of(vm_flags::write, vm_flags::exact); + obj::vm_area *vma = new obj::vm_area_fixed(addr, 0x1000, flags); + vm_space::kernel_space().add(addr, vma, flags); + memcpy( reinterpret_cast(addr), reinterpret_cast(&ap_startup), @@ -67,7 +70,7 @@ start(cpu_data &bsp, void *kpml4) size_t free_stack_count = 0; lapic &apic = *bsp.apic; - lapic::ipi mode = lapic::ipi::init | lapic::ipi::level | lapic::ipi::assert; + util::bitset32 mode = lapic::ipi_init + lapic::ipi_flags::level + lapic::ipi_flags::assert; apic.send_ipi_broadcast(mode, false, static_cast(0)); for (uint8_t id : ids) { @@ -90,7 +93,7 @@ start(cpu_data &bsp, void *kpml4) size_t current_count = ap_startup_count; log::verbose(logs::boot, "Starting AP %d: stack %llx", cpu->index, stack_end); - lapic::ipi startup = lapic::ipi::startup | lapic::ipi::assert; + util::bitset32 startup = lapic::ipi_sipi + lapic::ipi_flags::assert; apic.send_ipi(startup, vector, id); for (unsigned i = 0; i < 20; ++i) { diff --git a/src/kernel/syscalls/system.cpp b/src/kernel/syscalls/system.cpp index 7285a5d..ec26a6a 100644 --- a/src/kernel/syscalls/system.cpp +++ b/src/kernel/syscalls/system.cpp @@ -67,12 +67,11 @@ system_map_phys(system *self, j6_handle_t * area, uintptr_t phys, size_t size, u { // 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)) + util::bitset32 f = flags & vm_driver_mask; + if (!f.get(vm_flags::mmio)) 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); - + construct_handle(area, phys, size, f); return j6_status_ok; } diff --git a/src/kernel/syscalls/vm_area.cpp b/src/kernel/syscalls/vm_area.cpp index 4c065e8..72a2d7c 100644 --- a/src/kernel/syscalls/vm_area.cpp +++ b/src/kernel/syscalls/vm_area.cpp @@ -14,8 +14,8 @@ namespace syscalls { j6_status_t vma_create(j6_handle_t *self, size_t size, uint32_t flags) { - vm_flags f = vm_flags::user_mask & flags; - if (util::bits::has(f, vm_flags::ring)) + util::bitset32 f = flags & vm_user_mask; + if (f.get(vm_flags::ring)) construct_handle(self, size, f); else construct_handle(self, size, f); @@ -26,8 +26,8 @@ j6_status_t vma_create_map(j6_handle_t *self, size_t size, uintptr_t *base, uint32_t flags) { vm_area *a = nullptr; - vm_flags f = vm_flags::user_mask & flags; - if (util::bits::has(f, vm_flags::ring)) + util::bitset32 f = flags & vm_user_mask; + if (f.get(vm_flags::ring)) a = construct_handle(self, size, f); else a = construct_handle(self, size, f); @@ -40,7 +40,7 @@ j6_status_t vma_map(vm_area *self, process *proc, uintptr_t *base, uint32_t flags) { vm_space &space = proc ? proc->space() : process::current().space(); - vm_flags f = vm_flags::user_mask & flags; + util::bitset32 f = flags & vm_user_mask; *base = space.add(*base, self, f); return *base ? j6_status_ok : j6_err_collision; } diff --git a/src/kernel/vm_space.cpp b/src/kernel/vm_space.cpp index 011b054..1172af4 100644 --- a/src/kernel/vm_space.cpp +++ b/src/kernel/vm_space.cpp @@ -55,9 +55,9 @@ vm_space::vm_space() : obj::vm_area *sysc = new obj::vm_area_fixed( g_sysconf_phys, sizeof(system_config), - vm_flags::none); + 0); - add(sysconf_user_address, sysc, vm_flags::exact); + add(sysconf_user_address, sysc, util::bitset32::of(vm_flags::exact)); } vm_space::~vm_space() @@ -81,7 +81,7 @@ vm_space::kernel_space() } uintptr_t -vm_space::add(uintptr_t base, obj::vm_area *area, obj::vm_flags flags) +vm_space::add(uintptr_t base, obj::vm_area *area, util::bitset32 flags) { if (!base) base = min_auto_address; @@ -89,7 +89,7 @@ vm_space::add(uintptr_t base, obj::vm_area *area, obj::vm_flags flags) uintptr_t end = base + area->size(); //TODO: optimize find/insert - bool exact = util::bits::has(flags, j6_vm_flag_exact); + bool exact = flags.get(vm_flags::exact); for (size_t i = 0; i < m_areas.count(); ++i) { const vm_space::area &a = m_areas[i]; uintptr_t aend = a.base + a.area->size(); @@ -192,7 +192,7 @@ vm_space::copy_from(const vm_space &source, const obj::vm_area &vma) while (count--) { uint64_t &e = dit.entry(page_table::level::pt); - if (e & page_table::flag::present) { + if (util::bitset64::from(e) & page_flags::present) { // TODO: handle clobbering mapping } e = sit.entry(page_table::level::pt); @@ -210,11 +210,11 @@ vm_space::page_in(const obj::vm_area &vma, uintptr_t offset, uintptr_t phys, siz 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); + util::bitset64 flags = + page_flags::present | + (m_kernel ? page_flags::none : page_flags::user) | + (vma.flags().get(vm_flags::write) ? page_flags::write : page_flags::none) | + (vma.flags().get(vm_flags::write_combine) ? page_flags::wc : page_flags::none); page_table::iterator it {virt, m_pml4}; @@ -222,7 +222,7 @@ vm_space::page_in(const obj::vm_area &vma, uintptr_t offset, uintptr_t phys, siz uint64_t &entry = it.entry(page_table::level::pt); entry = (phys + i * frame_size) | flags; log::spam(logs::paging, "Setting entry for %016llx: %016llx [%04llx]", - it.vaddress(), (phys + i * frame_size), flags); + it.vaddress(), (phys + i * frame_size), flags.value()); ++it; } } @@ -247,11 +247,11 @@ vm_space::clear(const obj::vm_area &vma, uintptr_t offset, size_t count, bool fr while (count--) { uint64_t &e = it.entry(page_table::level::pt); uintptr_t phys = e & ~0xfffull; + util::bitset64 flags = e; - if (e & page_table::flag::present) { - uint64_t orig = e; + if (flags & page_flags::present) { e = 0; - if (orig & page_table::flag::accessed) { + if (flags & page_flags::accessed) { auto *addr = reinterpret_cast(it.vaddress()); asm ( "invlpg %0" :: "m"(*addr) : "memory" ); } @@ -290,11 +290,11 @@ vm_space::lock(const obj::vm_area &vma, uintptr_t offset, size_t count) while (count--) { uint64_t &e = it.entry(page_table::level::pt); uintptr_t phys = e & ~0xfffull; + util::bitset64 flags = e; - if (e & page_table::flag::present) { - uint64_t orig = e; + if (flags & page_flags::present) { e = locked_page_tag; - if (orig & page_table::flag::accessed) { + if (flags & page_flags::accessed) { auto *addr = reinterpret_cast(it.vaddress()); asm ( "invlpg %0" :: "m"(*addr) : "memory" ); } @@ -338,10 +338,10 @@ vm_space::initialize_tcb(TCB &tcb) } bool -vm_space::handle_fault(uintptr_t addr, fault_type fault) +vm_space::handle_fault(uintptr_t addr, util::bitset8 fault) { // TODO: Handle more fult types - if (fault && fault_type::present) + if (fault.get(fault_type::present)) return false; uintptr_t page = (addr & ~0xfffull); diff --git a/src/kernel/vm_space.h b/src/kernel/vm_space.h index ec5044e..997f723 100644 --- a/src/kernel/vm_space.h +++ b/src/kernel/vm_space.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include @@ -39,7 +39,7 @@ public: /// \arg area The area to add /// \arg flags Flags for the operation (exact, clobber, etc) /// \returns The base address the area was added at - uintptr_t add(uintptr_t base, obj::vm_area *area, obj::vm_flags flags); + uintptr_t add(uintptr_t base, obj::vm_area *area, util::bitset32 flags); /// Remove a virtual memory area from this address space /// \arg area The area to remove @@ -88,15 +88,6 @@ public: /// 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 - }; - /// 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 @@ -104,11 +95,13 @@ public: /// \returns The number of pages actually allocated size_t allocate(uintptr_t virt, size_t count, uintptr_t *phys); + enum class fault_type { present, write, user, reserved, fetch }; + /// 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); + bool handle_fault(uintptr_t addr, util::bitset8 fault); /// Set up a TCB to operate in this address space. void initialize_tcb(TCB &tcb); @@ -155,6 +148,4 @@ private: util::vector m_areas; util::spinlock m_lock; -}; - -is_bitfield(vm_space::fault_type); +}; \ No newline at end of file diff --git a/src/libraries/bootproto/include/bootproto/bootconfig.h b/src/libraries/bootproto/include/bootproto/bootconfig.h index 32721c7..e579e36 100644 --- a/src/libraries/bootproto/include/bootproto/bootconfig.h +++ b/src/libraries/bootproto/include/bootproto/bootconfig.h @@ -3,15 +3,9 @@ /// Data structures for reading jsix_boot.dat #include -#include namespace bootproto { -enum class desc_flags : uint16_t { - graphical = 0x0001, - panic = 0x0002, - symbols = 0x0004, -}; -is_bitfield(desc_flags); +enum class desc_flags { graphical, panic, symbols }; } // namespace bootproto diff --git a/src/libraries/bootproto/include/bootproto/kernel.h b/src/libraries/bootproto/include/bootproto/kernel.h index d834a96..a4227b3 100644 --- a/src/libraries/bootproto/include/bootproto/kernel.h +++ b/src/libraries/bootproto/include/bootproto/kernel.h @@ -6,8 +6,8 @@ #include #include +#include #include -#include namespace bootproto { @@ -18,19 +18,13 @@ constexpr uint64_t header_magic = 0x4c454e52454b366aull; // 'j6KERNEL' 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, -}; -is_bitfield(section_flags); +enum class section_flags { none, execute, write, read }; struct program_section { uintptr_t phys_addr; uintptr_t virt_addr; uint32_t size; - section_flags type; + util::bitset32 type; }; struct program { @@ -112,18 +106,13 @@ struct frame_block uint64_t *bitmap; }; -enum class boot_flags : uint16_t { - none = 0x0000, - debug = 0x0001, - test = 0x0002, -}; -is_bitfield(boot_flags); +enum class boot_flags { none, debug, test }; struct args { uint32_t magic; uint16_t version; - boot_flags flags; + util::bitset16 flags; void *pml4; util::counted page_tables; diff --git a/src/libraries/cpu/include/cpu/cpu_id.h b/src/libraries/cpu/include/cpu/cpu_id.h index 9181b61..acfc492 100644 --- a/src/libraries/cpu/include/cpu/cpu_id.h +++ b/src/libraries/cpu/include/cpu/cpu_id.h @@ -18,7 +18,7 @@ enum class feature { max }; -using features = util::bitset<(unsigned)feature::max>; +using features = util::sized_bitset<(unsigned)feature::max>; class cpu_id { diff --git a/src/libraries/elf/include/elf/headers.h b/src/libraries/elf/include/elf/headers.h index 1afc292..c65119e 100644 --- a/src/libraries/elf/include/elf/headers.h +++ b/src/libraries/elf/include/elf/headers.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace elf { @@ -54,19 +54,12 @@ struct file_header enum class segment_type : uint32_t { null, load, dynamic, interpreter, note }; -enum class segment_flags : uint32_t -{ - none = 0x00, - exec = 0x01, - write = 0x02, - read = 0x04, -}; -is_bitfield(segment_flags); +enum class segment_flags { exec, write, read }; struct segment_header { segment_type type; - segment_flags flags; + util::bitset32 flags; uint64_t offset; uint64_t vaddr; @@ -80,18 +73,13 @@ struct segment_header enum class section_type : uint32_t { null, progbits }; -enum class section_flags : uint64_t -{ - write = 0x01, - alloc = 0x02, - exec = 0x04, -}; +enum class section_flags { write, alloc, exec }; struct section_header { uint32_t name_offset; section_type type; - section_flags flags; + util::bitset64 flags; uint64_t addr; uint64_t offset; uint64_t size; @@ -102,5 +90,3 @@ struct section_header } __attribute__ ((packed)); } // namespace elf - -is_bitfield(elf::section_flags); diff --git a/src/libraries/j6/include/j6/flags.h b/src/libraries/j6/include/j6/flags.h index 0d7e91c..c63d8a7 100644 --- a/src/libraries/j6/include/j6/flags.h +++ b/src/libraries/j6/include/j6/flags.h @@ -3,7 +3,8 @@ /// Enums used as flags for syscalls enum j6_vm_flags { -#define VM_FLAG(name, v) j6_vm_flag_ ## name = v, + j6_vm_flag_none = 0, +#define VM_FLAG(name, v) j6_vm_flag_ ## name = (1ul << v), #include #undef VM_FLAG j6_vm_flag_MAX diff --git a/src/libraries/j6/include/j6/tables/vm_flags.inc b/src/libraries/j6/include/j6/tables/vm_flags.inc index 1ced26d..2181ce6 100644 --- a/src/libraries/j6/include/j6/tables/vm_flags.inc +++ b/src/libraries/j6/include/j6/tables/vm_flags.inc @@ -1,15 +1,13 @@ -VM_FLAG( none, 0x00000000 ) +VM_FLAG( write, 0 ) +VM_FLAG( exec, 1 ) -VM_FLAG( write, 0x00000001 ) -VM_FLAG( exec, 0x00000002 ) +VM_FLAG( contiguous, 4 ) +VM_FLAG( large_pages, 5 ) +VM_FLAG( huge_pages, 6 ) -VM_FLAG( contiguous, 0x00000010 ) -VM_FLAG( large_pages, 0x00000020 ) -VM_FLAG( huge_pages, 0x00000040 ) +VM_FLAG( write_combine, 8 ) -VM_FLAG( write_combine, 0x00000100 ) +VM_FLAG( mmio, 12 ) -VM_FLAG( mmio, 0x00001000 ) - -VM_FLAG( exact, 0x00010000 ) -VM_FLAG( ring, 0x00020000 ) \ No newline at end of file +VM_FLAG( exact, 16 ) +VM_FLAG( ring, 17 ) \ No newline at end of file diff --git a/src/libraries/util/include/util/bitset.h b/src/libraries/util/include/util/bitset.h index 2788777..6f81bf7 100644 --- a/src/libraries/util/include/util/bitset.h +++ b/src/libraries/util/include/util/bitset.h @@ -7,34 +7,148 @@ namespace util { /// A statically-sized templated bitset -template +template class bitset +{ +public: + using storage_type = I; + +private: + template + static constexpr storage_type bit_or(T b) { return 1ull << uint64_t(b); } + + template + static constexpr storage_type bit_or(T b, Args... bs) { return (1ull << storage_type(b)) | bit_or(bs...); } + +public: + constexpr bitset(storage_type v = 0) : m_bits {v} {} + + constexpr bitset(const bitset &o) : m_bits {o.m_bits} {} + + template + __attribute__ ((always_inline)) + static constexpr bitset of(Args... args) { return {bit_or(args...)}; } + + template + __attribute__ ((always_inline)) + static constexpr bitset from(T i) { return {storage_type(i)}; } + + __attribute__ ((always_inline)) + inline constexpr bitset & operator=(bitset b) { m_bits = b.m_bits; return *this; } + + inline constexpr operator storage_type () const { return m_bits; } + + template + __attribute__ ((always_inline)) + inline constexpr bool get(T i) const { + return m_bits & bit(i); + } + + template + __attribute__ ((always_inline)) + inline bitset & set(T i) { + m_bits |= bit(i); + return *this; + } + + template + __attribute__ ((always_inline)) + inline bitset & clear(T i) { + m_bits &= ~bit(i); + return *this; + } + + __attribute__ ((always_inline)) + inline storage_type range(unsigned start, unsigned count) { + return (m_bits >> start) & ~((1 << count) - 1); + } + + __attribute__ ((always_inline)) + inline bitset & set_range(unsigned start, unsigned count, storage_type val) { + const storage_type mask = ~((1 << count) - 1) << start; + m_bits = (m_bits & ~mask) | ((val << start) & mask); + return *this; + } + + template + __attribute__ ((always_inline)) + inline constexpr bool operator[](T i) const { return get(i); } + + __attribute__ ((always_inline)) + inline constexpr bitset operator|(bitset b) const { return {storage_type(m_bits | b.m_bits)}; } + + template + __attribute__ ((always_inline)) + inline constexpr bitset operator+(T i) const { return {storage_type(m_bits | bit(i))}; } + + __attribute__ ((always_inline)) + inline constexpr bitset operator|=(bitset b) { *this = *this|b; return *this; } + + template + __attribute__ ((always_inline)) + inline constexpr bitset operator+=(T i) { set(i); return *this; } + + __attribute__ ((always_inline)) + inline constexpr bitset operator&(const bitset &b) const { return {storage_type(m_bits & b.m_bits)}; } + + template + __attribute__ ((always_inline)) + inline constexpr bitset operator&(T i) const { return {m_bits & bit(i)}; } + + __attribute__ ((always_inline)) + inline constexpr bitset & operator&=(const bitset &b) { m_bits &= b.m_bits; return *this; } + + __attribute__ ((always_inline)) + inline constexpr bool operator==(const bitset &b) const { return m_bits == b.m_bits; } + + template + __attribute__ ((always_inline)) + inline constexpr bool operator==(T i) const { return m_bits == storage_type(i); } + + inline constexpr bool empty() const { return m_bits == 0; } + + inline constexpr uint64_t value() const { return m_bits; } + +private: + template + inline constexpr storage_type bit(T i) const { return (storage_type(1) << int(i)); } + + storage_type m_bits; +}; + +using bitset64 = bitset; +using bitset32 = bitset; +using bitset16 = bitset; +using bitset8 = bitset; + +template +class sized_bitset { static constexpr unsigned num_elems = (N + 63) / 64; public: template - __attribute__ ((force_inline)) + __attribute__ ((always_inline)) inline bool get(T i) const { return bits(i) & bit(i); } template - __attribute__ ((force_inline)) - inline bitset & set(T i) { + __attribute__ ((always_inline)) + inline sized_bitset & set(T i) { bits(i) |= bit(i); return *this; } template - __attribute__ ((force_inline)) - inline bitset & clear(T i) { + __attribute__ ((always_inline)) + inline sized_bitset & clear(T i) { bits(i) &= ~bit(i); return *this; } template - __attribute__ ((force_inline)) + __attribute__ ((always_inline)) inline bool operator[](T i) const { return get(i); } inline bool empty() const { @@ -45,260 +159,18 @@ public: private: template - __attribute__ ((force_inline)) + __attribute__ ((always_inline)) inline uint64_t bit(T i) const { return (1ull << (static_cast(i) & 63)); } template - __attribute__ ((force_inline)) + __attribute__ ((always_inline)) inline uint64_t &bits(T i) { return m_bits[static_cast(i) >> 6]; } template - __attribute__ ((force_inline)) + __attribute__ ((always_inline)) inline uint64_t bits(T i) const { return m_bits[static_cast(i) >> 6]; } uint64_t m_bits[num_elems] = {0}; }; -namespace { -} - -/// A statically-sized templated bitset -template <> -class bitset<64> -{ - template - static constexpr uint64_t bit_or(T b) { return 1ull << uint64_t(b); } - - template - static constexpr uint64_t bit_or(T b, Args... bs) { return (1ull << uint64_t(b)) | bit_or(bs...); } - -public: - bitset(uint64_t v = 0) : m_bits {v} {} - - bitset(const bitset<64> &o) : m_bits {o.m_bits} {} - - template - constexpr explicit bitset(Args... args) : m_bits(bit_or(args...)) {} - - template - __attribute__ ((force_inline)) - inline bitset & operator=(T v) { m_bits = static_cast(v); return *this; } - - inline constexpr operator const uint64_t () const { return m_bits; } - - template - __attribute__ ((force_inline)) - inline constexpr bool get(T i) const { - return m_bits & bit(i); - } - - template - __attribute__ ((force_inline)) - inline bitset & set(T i) { - m_bits |= bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline bitset & clear(T i) { - m_bits &= ~bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline constexpr bool operator[](T i) const { return get(i); } - - inline constexpr bool empty() const { return m_bits == 0; } - - inline constexpr uint64_t value() const { return m_bits; } - -private: - template - inline constexpr uint64_t bit(T i) const { return (1ull << static_cast(i)); } - - uint64_t m_bits; -}; - -/// A statically-sized templated bitset -template <> -class bitset<32> -{ - template - static constexpr uint32_t bit_or(T b) { return 1u << uint32_t(b); } - - template - static constexpr uint32_t bit_or(T b, Args... bs) { return (1u << uint32_t(b)) | bit_or(bs...); } - -public: - bitset(uint32_t v = 0) : m_bits {v} {} - - bitset(const bitset<32> &o) : m_bits {o.m_bits} {} - - template - constexpr bitset(Args... args) : m_bits(bit_or(args...)) {} - - template - inline bitset & operator=(T v) { m_bits = static_cast(v); return *this; } - - inline constexpr operator uint32_t () const { return m_bits; } - - template - __attribute__ ((force_inline)) - inline constexpr bool get(T i) const { - return m_bits & bit(i); - } - - template - __attribute__ ((force_inline)) - inline bitset & set(T i) { - m_bits |= bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline bitset & clear(T i) { - m_bits &= ~bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline bool operator[](T i) const { return get(i); } - - inline bool empty() const { return m_bits == 0; } - - inline constexpr uint32_t value() const { return m_bits; } - -private: - template - inline uint32_t bit(T i) const { return (1u << static_cast(i)); } - - uint32_t m_bits; -}; - -/// A statically-sized templated bitset -template <> -class bitset<16> -{ - template - static constexpr uint16_t bit_or(T b) { return 1u << uint16_t(b); } - - template - static constexpr uint16_t bit_or(T b, Args... bs) { return (1u << uint16_t(b)) | bit_or(bs...); } - -public: - bitset(uint16_t v = 0) : m_bits {v} {} - - bitset(const bitset<16> &o) : m_bits {o.m_bits} {} - - template - constexpr bitset(Args... args) : m_bits(bit_or(args...)) {} - - template - inline bitset & operator=(T v) { m_bits = static_cast(v); return *this; } - - inline constexpr operator uint16_t () const { return m_bits; } - - template - __attribute__ ((force_inline)) - inline constexpr bool get(T i) const { - return m_bits & bit(i); - } - - template - __attribute__ ((force_inline)) - inline bitset & set(T i) { - m_bits |= bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline bitset & clear(T i) { - m_bits &= ~bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline bool operator[](T i) const { return get(i); } - - inline bool empty() const { return m_bits == 0; } - - inline constexpr uint16_t value() const { return m_bits; } - -private: - template - inline uint16_t bit(T i) const { return (1u << static_cast(i)); } - - uint16_t m_bits; -}; - - -/// A statically-sized templated bitset -template <> -class bitset<8> -{ - template - static constexpr uint8_t bit_or(T b) { return 1u << uint8_t(b); } - - template - static constexpr uint8_t bit_or(T b, Args... bs) { return (1u << uint8_t(b)) | bit_or(bs...); } - -public: - bitset(uint8_t v = 0) : m_bits {v} {} - - bitset(const bitset<8> &o) : m_bits {o.m_bits} {} - - template - constexpr bitset(Args... args) : m_bits(bit_or(args...)) {} - - template - inline bitset & operator=(T v) { m_bits = static_cast(v); return *this; } - - inline constexpr operator uint8_t () const { return m_bits; } - - template - __attribute__ ((force_inline)) - inline constexpr bool get(T i) const { - return m_bits & bit(i); - } - - template - __attribute__ ((force_inline)) - inline bitset & set(T i) { - m_bits |= bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline bitset & clear(T i) { - m_bits &= ~bit(i); - return *this; - } - - template - __attribute__ ((force_inline)) - inline bool operator[](T i) const { return get(i); } - - inline bool empty() const { return m_bits == 0; } - - inline constexpr uint8_t value() const { return m_bits; } - -private: - template - inline uint8_t bit(T i) const { return (1u << static_cast(i)); } - - uint8_t m_bits; -}; - -using bitset64 = bitset<64>; -using bitset32 = bitset<32>; -using bitset16 = bitset<16>; -using bitset8 = bitset<8>; - } // namespace util diff --git a/src/libraries/util/include/util/enum_bitfields.h b/src/libraries/util/include/util/enum_bitfields.h deleted file mode 100644 index 91ae191..0000000 --- a/src/libraries/util/include/util/enum_bitfields.h +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#include - -namespace util { -namespace bits { - -template -constexpr bool is_enum_bitfield(E) { return false; } - -template -struct enum_or_int { - static constexpr bool value = - is_enum_bitfield(typename types::non_const::type{}) - || types::is_integral::value; -}; - -template -struct both_enum_or_int { - static constexpr bool value = - types::conjunction< enum_or_int, enum_or_int >::value; -}; - -template -struct enable_if_bitfield { - using enum_t = typename types::non_const::type; - using type = typename - types::enable_if< is_enum_bitfield(enum_t{}), R >::type; -}; - -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)); -} - -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)); -} - -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)); -} - -template -constexpr typename types::enable_if::value,E>::type -operator & (E lhs, F rhs) { return lhs &= rhs; } - -template -constexpr typename types::enable_if::value,E>::type -operator | (E lhs, F rhs) { return lhs |= rhs; } - -template -constexpr typename types::enable_if::value,E>::type -operator ^ (E lhs, F rhs) { return lhs ^= rhs; } - -template -constexpr typename enable_if_bitfield::type -operator ~ (E rhs) { return static_cast(~static_cast::type>(rhs)); } - -template -constexpr typename enable_if_bitfield::type -operator ! (E rhs) { return static_cast::type>(rhs) == 0; } - -/// Override logical-and to mean 'rhs contains all bits in lhs' -template -constexpr typename enable_if_bitfield::type -operator && (E rhs, E lhs) { return (rhs & lhs) == lhs; } - -/// Generic 'has' for non-marked bitfields -template -constexpr bool has(E set, F flags) -{ - return - (static_cast::type>(set) & - static_cast::type>(flags)) == - static_cast::type>(flags); -} - -} // namespace bits -} // namespace util - -#define is_bitfield(name) \ - constexpr bool is_enum_bitfield(name) { return true; } \ - using namespace ::util::bits; - diff --git a/src/libraries/util/util.module b/src/libraries/util/util.module index 7c58866..8994018 100644 --- a/src/libraries/util/util.module +++ b/src/libraries/util/util.module @@ -20,7 +20,6 @@ module("util", "util/cdb.h", "util/counted.h", "util/deque.h", - "util/enum_bitfields.h", "util/format.h", "util/hash.h", "util/linked_list.h", diff --git a/src/user/ld.so/image.cpp b/src/user/ld.so/image.cpp index 82e2c4b..829f072 100644 --- a/src/user/ld.so/image.cpp +++ b/src/user/ld.so/image.cpp @@ -94,7 +94,7 @@ load_image(image_list::item_type &img, j6::proto::vfs::client &vfs) // TODO: way to remap VMA as read-only if there's no write flag on // the segment unsigned long flags = j6_vm_flag_exact | j6_vm_flag_write; - if (seg.flags && elf::segment_flags::exec) + if (seg.flags.get(elf::segment_flags::exec)) flags |= j6_vm_flag_exec; uintptr_t start = file.base() + seg.offset; diff --git a/src/user/srv.init/j6romfs.h b/src/user/srv.init/j6romfs.h index c859e78..234f7c8 100644 --- a/src/user/srv.init/j6romfs.h +++ b/src/user/srv.init/j6romfs.h @@ -3,7 +3,6 @@ /// Data structure for dealing with j6romfs images #include -#include namespace j6romfs { diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index 12ee52e..febd3b7 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -95,7 +95,7 @@ load_program_into(j6_handle_t proc, elf::file &file, uintptr_t image_base, const // TODO: way to remap VMA as read-only if there's no write flag on // the segment unsigned long flags = j6_vm_flag_write; - if (seg.flags && elf::segment_flags::exec) + if (seg.flags.get(elf::segment_flags::exec)) flags |= j6_vm_flag_exec; uintptr_t start = file.base() + seg.offset;