[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).
This commit is contained in:
@@ -22,7 +22,7 @@ read_string(util::buffer &data)
|
|||||||
static void
|
static void
|
||||||
read_descriptor(descriptor &e, util::buffer &data)
|
read_descriptor(descriptor &e, util::buffer &data)
|
||||||
{
|
{
|
||||||
e.flags = static_cast<desc_flags>(*util::read<uint16_t>(data));
|
e.flags = util::bitset16 {*util::read<uint16_t>(data)};
|
||||||
e.path = read_string(data);
|
e.path = read_string(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <bootproto/bootconfig.h>
|
#include <bootproto/bootconfig.h>
|
||||||
|
#include <util/bitset.h>
|
||||||
#include <util/counted.h>
|
#include <util/counted.h>
|
||||||
|
|
||||||
namespace uefi {
|
namespace uefi {
|
||||||
@@ -14,7 +15,7 @@ namespace boot {
|
|||||||
using desc_flags = bootproto::desc_flags;
|
using desc_flags = bootproto::desc_flags;
|
||||||
|
|
||||||
struct descriptor {
|
struct descriptor {
|
||||||
desc_flags flags;
|
util::bitset16 flags;
|
||||||
wchar_t const *path;
|
wchar_t const *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ public:
|
|||||||
/// Constructor. Loads bootconfig from the given buffer.
|
/// Constructor. Loads bootconfig from the given buffer.
|
||||||
bootconfig(util::buffer data, uefi::boot_services *bs);
|
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 & kernel() const { return m_kernel; }
|
||||||
inline const descriptor & init() const { return m_init; }
|
inline const descriptor & init() const { return m_init; }
|
||||||
inline const wchar_t * initrd() const { return m_initrd; }
|
inline const wchar_t * initrd() const { return m_initrd; }
|
||||||
@@ -35,7 +36,7 @@ public:
|
|||||||
inline const descriptors & panics() { return m_panics; }
|
inline const descriptors & panics() { return m_panics; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t m_flags;
|
util::bitset16 m_flags;
|
||||||
descriptor m_kernel;
|
descriptor m_kernel;
|
||||||
descriptor m_init;
|
descriptor m_init;
|
||||||
descriptors m_panics;
|
descriptors m_panics;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ parse_program(const wchar_t *name, util::const_buffer data, bootproto::program &
|
|||||||
section.phys_addr = elf.base() + seg.offset;
|
section.phys_addr = elf.base() + seg.offset;
|
||||||
section.virt_addr = seg.vaddr;
|
section.virt_addr = seg.vaddr;
|
||||||
section.size = seg.mem_size;
|
section.size = seg.mem_size;
|
||||||
section.type = static_cast<bootproto::section_flags>(seg.flags);
|
section.type = seg.flags;
|
||||||
|
|
||||||
if (seg.mem_size != seg.file_size)
|
if (seg.mem_size != seg.file_size)
|
||||||
section.phys_addr = allocate_bss(seg);
|
section.phys_addr = allocate_bss(seg);
|
||||||
@@ -128,8 +128,6 @@ load_program(
|
|||||||
paging::pager &pager,
|
paging::pager &pager,
|
||||||
bool verify)
|
bool verify)
|
||||||
{
|
{
|
||||||
using util::bits::has;
|
|
||||||
|
|
||||||
status_line status(L"Loading program", name);
|
status_line status(L"Loading program", name);
|
||||||
|
|
||||||
elf::file elf {data};
|
elf::file elf {data};
|
||||||
@@ -155,8 +153,8 @@ load_program(
|
|||||||
|
|
||||||
pager.map_pages(phys_addr, seg.vaddr,
|
pager.map_pages(phys_addr, seg.vaddr,
|
||||||
memory::bytes_to_pages(seg.mem_size),
|
memory::bytes_to_pages(seg.mem_size),
|
||||||
has(seg.flags, elf::segment_flags::write),
|
seg.flags.get(elf::segment_flags::write),
|
||||||
has(seg.flags, elf::segment_flags::exec));
|
seg.flags.get(elf::segment_flags::exec));
|
||||||
}
|
}
|
||||||
|
|
||||||
return elf.entrypoint();
|
return elf.entrypoint();
|
||||||
|
|||||||
@@ -82,9 +82,8 @@ load_resources(
|
|||||||
util::buffer kernel = loader::load_file(disk, bc.kernel().path);
|
util::buffer kernel = loader::load_file(disk, bc.kernel().path);
|
||||||
uintptr_t kentry = loader::load_program(kernel, L"jsix kernel", pager, true);
|
uintptr_t kentry = loader::load_program(kernel, L"jsix kernel", pager, true);
|
||||||
|
|
||||||
args->flags = static_cast<bootproto::boot_flags>(bc.flags());
|
args->flags = bc.flags();
|
||||||
|
|
||||||
namespace bits = util::bits;
|
|
||||||
using bootproto::desc_flags;
|
using bootproto::desc_flags;
|
||||||
|
|
||||||
bool has_panic = false;
|
bool has_panic = false;
|
||||||
@@ -96,7 +95,7 @@ load_resources(
|
|||||||
// Find the screen-specific panic handler first to
|
// Find the screen-specific panic handler first to
|
||||||
// give it priority
|
// give it priority
|
||||||
for (const descriptor &d : bc.panics()) {
|
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);
|
panic = loader::load_file(disk, d.path);
|
||||||
has_panic = true;
|
has_panic = true;
|
||||||
break;
|
break;
|
||||||
@@ -106,7 +105,7 @@ load_resources(
|
|||||||
|
|
||||||
if (!has_panic) {
|
if (!has_panic) {
|
||||||
for (const descriptor &d : bc.panics()) {
|
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);
|
panic = loader::load_file(disk, d.path);
|
||||||
has_panic = true;
|
has_panic = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/bitset.h>
|
||||||
#include <util/misc.h> // for byteswap32
|
#include <util/misc.h> // for byteswap32
|
||||||
|
|
||||||
namespace acpi {
|
namespace acpi {
|
||||||
@@ -62,32 +62,31 @@ struct gas
|
|||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
enum class fadt_flags : uint32_t
|
enum class fadt_flags
|
||||||
{
|
{
|
||||||
wbinvd = 0x00000001,
|
wbinvd,
|
||||||
wbinvd_flush = 0x00000002,
|
wbinvd_flush,
|
||||||
proc_c1 = 0x00000004,
|
proc_c1,
|
||||||
p_lvl2_up = 0x00000008,
|
p_lvl2_up,
|
||||||
pwr_button = 0x00000010,
|
pwr_button,
|
||||||
slp_button = 0x00000020,
|
slp_button,
|
||||||
fix_rtc = 0x00000040,
|
fix_rtc,
|
||||||
rtc_s4 = 0x00000080,
|
rtc_s4,
|
||||||
tmr_val_ext = 0x00000100,
|
tmr_val_ext,
|
||||||
dck_cap = 0x00000200,
|
dck_cap,
|
||||||
reset_reg_sup = 0x00000400,
|
reset_reg_sup,
|
||||||
sealed_case = 0x00000800,
|
sealed_case,
|
||||||
headless = 0x00001000,
|
headless,
|
||||||
cpu_sw_slp = 0x00002000,
|
cpu_sw_slp,
|
||||||
pci_exp_wak = 0x00004000,
|
pci_exp_wak,
|
||||||
use_plat_clock = 0x00008000,
|
use_plat_clock,
|
||||||
s4_rtc_sts_val = 0x00010000,
|
s4_rtc_sts_val,
|
||||||
remote_pwr_cap = 0x00020000,
|
remote_pwr_cap,
|
||||||
apic_cluster = 0x00040000,
|
apic_cluster,
|
||||||
apic_physical = 0x00080000,
|
apic_physical,
|
||||||
hw_reduced_acpi = 0x00100000,
|
hw_reduced_acpi,
|
||||||
low_pwr_s0_idle = 0x00200000
|
low_pwr_s0_idle
|
||||||
};
|
};
|
||||||
is_bitfield(fadt_flags);
|
|
||||||
|
|
||||||
struct fadt
|
struct fadt
|
||||||
{
|
{
|
||||||
@@ -134,7 +133,7 @@ struct fadt
|
|||||||
|
|
||||||
uint16_t iapc_boot_arch;
|
uint16_t iapc_boot_arch;
|
||||||
uint8_t reserved1;
|
uint8_t reserved1;
|
||||||
fadt_flags flags;
|
util::bitset32 flags;
|
||||||
|
|
||||||
gas reset_reg;
|
gas reset_reg;
|
||||||
uint8_t reset_value;
|
uint8_t reset_value;
|
||||||
|
|||||||
@@ -71,21 +71,19 @@ lapic::get_id()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
// Wait until the APIC is ready to send
|
||||||
ipi_wait();
|
ipi_wait();
|
||||||
|
|
||||||
uint32_t command =
|
uint32_t command = util::bitset32::from(vector) | mode;
|
||||||
static_cast<uint32_t>(vector) |
|
|
||||||
static_cast<uint32_t>(mode);
|
|
||||||
|
|
||||||
apic_write(m_base, lapic_icr_high, static_cast<uint32_t>(dest) << 24);
|
apic_write(m_base, lapic_icr_high, static_cast<uint32_t>(dest) << 24);
|
||||||
apic_write(m_base, lapic_icr_low, command);
|
apic_write(m_base, lapic_icr_low, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
// Wait until the APIC is ready to send
|
||||||
ipi_wait();
|
ipi_wait();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// Classes to control both local and I/O APICs.
|
/// Classes to control both local and I/O APICs.
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/bitset.h>
|
||||||
|
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
|
|
||||||
@@ -33,33 +33,30 @@ public:
|
|||||||
/// Get the local APIC's ID
|
/// Get the local APIC's ID
|
||||||
uint8_t get_id();
|
uint8_t get_id();
|
||||||
|
|
||||||
enum class ipi : uint32_t
|
enum class ipi_flags
|
||||||
{
|
{
|
||||||
// Delivery modes
|
logical = 11,
|
||||||
fixed = 0x0000,
|
pending = 12,
|
||||||
smi = 0x0200,
|
assert = 14,
|
||||||
nmi = 0x0400,
|
level = 15,
|
||||||
init = 0x0500,
|
|
||||||
startup = 0x0600,
|
|
||||||
|
|
||||||
// Flags
|
|
||||||
deassert = 0x0000,
|
|
||||||
assert = 0x4000,
|
|
||||||
edge = 0x0000, ///< edge-triggered
|
|
||||||
level = 0x8000, ///< level-triggered
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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.
|
/// Send an inter-processor interrupt.
|
||||||
/// \arg mode The sending mode
|
/// \arg mode The sending mode
|
||||||
/// \arg vector The interrupt vector
|
/// \arg vector The interrupt vector
|
||||||
/// \arg dest The APIC ID of the destination
|
/// \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
|
/// Send an inter-processor broadcast interrupt to all other CPUs
|
||||||
/// \arg mode The sending mode
|
/// \arg mode The sending mode
|
||||||
/// \arg self If true, include this CPU in the broadcast
|
/// \arg self If true, include this CPU in the broadcast
|
||||||
/// \arg vector The interrupt vector
|
/// \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
|
/// Wait for an IPI to finish sending. This is done automatically
|
||||||
/// before sending another IPI with send_ipi().
|
/// before sending another IPI with send_ipi().
|
||||||
@@ -145,6 +142,3 @@ private:
|
|||||||
uint8_t m_id;
|
uint8_t m_id;
|
||||||
uint8_t m_version;
|
uint8_t m_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
is_bitfield(lapic::ipi);
|
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ cpu_early_init(cpu_data *cpu)
|
|||||||
set_xcr0(xcr0_val);
|
set_xcr0(xcr0_val);
|
||||||
|
|
||||||
// Set initial floating point state
|
// Set initial floating point state
|
||||||
const util::bitset32 mxcsr_val {
|
const util::bitset32 mxcsr_val = util::bitset32::of(
|
||||||
mxcsr::DAZ,
|
mxcsr::DAZ,
|
||||||
mxcsr::IM,
|
mxcsr::IM,
|
||||||
mxcsr::DM,
|
mxcsr::DM,
|
||||||
@@ -126,8 +126,7 @@ cpu_early_init(cpu_data *cpu)
|
|||||||
mxcsr::OM,
|
mxcsr::OM,
|
||||||
mxcsr::UM,
|
mxcsr::UM,
|
||||||
mxcsr::PM,
|
mxcsr::PM,
|
||||||
mxcsr::FTZ,
|
mxcsr::FTZ);
|
||||||
};
|
|
||||||
asm ( "ldmxcsr %0" :: "m"(mxcsr_val) );
|
asm ( "ldmxcsr %0" :: "m"(mxcsr_val) );
|
||||||
|
|
||||||
// Install the GS base pointint to the cpu_data
|
// Install the GS base pointint to the cpu_data
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ static constexpr uint8_t tss_index = 6; // Note that this takes TWO GDT en
|
|||||||
static util::no_construct<GDT> __g_bsp_gdt_storage;
|
static util::no_construct<GDT> __g_bsp_gdt_storage;
|
||||||
GDT &g_bsp_gdt = __g_bsp_gdt_storage.value;
|
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) :
|
GDT::GDT(TSS *tss) :
|
||||||
m_tss(tss)
|
m_tss(tss)
|
||||||
@@ -32,13 +35,13 @@ GDT::GDT(TSS *tss) :
|
|||||||
m_ptr.base = &m_entries[0];
|
m_ptr.base = &m_entries[0];
|
||||||
|
|
||||||
// Kernel CS/SS - always 64bit
|
// Kernel CS/SS - always 64bit
|
||||||
set(kern_cs_index, 0, 0xfffff, true, type::read_write | type::execute);
|
set(kern_cs_index, 0, 0xfffff, true, rwx);
|
||||||
set(kern_ss_index, 0, 0xfffff, true, type::read_write);
|
set(kern_ss_index, 0, 0xfffff, true, rw);
|
||||||
|
|
||||||
// User CS32/SS/CS64 - layout expected by SYSRET
|
// User CS32/SS/CS64 - layout expected by SYSRET
|
||||||
set(user_cs32_index, 0, 0xfffff, false, type::ring3 | type::read_write | type::execute);
|
set(user_cs32_index, 0, 0xfffff, false, ring3 | rwx);
|
||||||
set(user_ss_index, 0, 0xfffff, true, type::ring3 | type::read_write);
|
set(user_ss_index, 0, 0xfffff, true, ring3 | rw);
|
||||||
set(user_cs64_index, 0, 0xfffff, true, type::ring3 | type::read_write | type::execute);
|
set(user_cs64_index, 0, 0xfffff, true, ring3 | rwx);
|
||||||
|
|
||||||
set_tss(tss);
|
set_tss(tss);
|
||||||
}
|
}
|
||||||
@@ -61,7 +64,7 @@ GDT::install() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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].limit_low = limit & 0xffff;
|
||||||
m_entries[i].size = (limit >> 16) & 0xf;
|
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_mid = (base >> 16) & 0xff;
|
||||||
m_entries[i].base_high = (base >> 24) & 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
|
struct tss_descriptor
|
||||||
@@ -79,7 +84,7 @@ struct tss_descriptor
|
|||||||
uint16_t limit_low;
|
uint16_t limit_low;
|
||||||
uint16_t base_00;
|
uint16_t base_00;
|
||||||
uint8_t base_16;
|
uint8_t base_16;
|
||||||
GDT::type type;
|
util::bitset8 type;
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint8_t base_24;
|
uint8_t base_24;
|
||||||
uint32_t base_32;
|
uint32_t base_32;
|
||||||
@@ -102,11 +107,9 @@ GDT::set_tss(TSS *tss)
|
|||||||
tssd.base_32 = (base >> 32) & 0xffffffff;
|
tssd.base_32 = (base >> 32) & 0xffffffff;
|
||||||
tssd.reserved = 0;
|
tssd.reserved = 0;
|
||||||
|
|
||||||
tssd.type =
|
static constexpr util::bitset8 tss_mark =
|
||||||
type::accessed |
|
util::bitset8::of(type::accessed, type::execute, type::present);
|
||||||
type::execute |
|
tssd.type = ring3 | tss_mark;
|
||||||
type::ring3 |
|
|
||||||
type::present;
|
|
||||||
|
|
||||||
memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor));
|
memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// Definitions relating to a CPU's GDT table
|
/// Definitions relating to a CPU's GDT table
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/bitset.h>
|
||||||
|
|
||||||
class TSS;
|
class TSS;
|
||||||
|
|
||||||
@@ -25,21 +25,20 @@ public:
|
|||||||
/// \arg index Which entry to print, or -1 for all entries
|
/// \arg index Which entry to print, or -1 for all entries
|
||||||
void dump(unsigned index = -1) const;
|
void dump(unsigned index = -1) const;
|
||||||
|
|
||||||
enum class type : uint8_t
|
enum class type
|
||||||
{
|
{
|
||||||
accessed = 0x01,
|
accessed,
|
||||||
read_write = 0x02,
|
read_write,
|
||||||
conforming = 0x04,
|
conforming,
|
||||||
execute = 0x08,
|
execute,
|
||||||
system = 0x10,
|
system,
|
||||||
ring1 = 0x20,
|
ring1,
|
||||||
ring2 = 0x40,
|
ring2,
|
||||||
ring3 = 0x60,
|
present
|
||||||
present = 0x80
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
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);
|
void set_tss(TSS *tss);
|
||||||
|
|
||||||
struct descriptor
|
struct descriptor
|
||||||
@@ -47,7 +46,7 @@ private:
|
|||||||
uint16_t limit_low;
|
uint16_t limit_low;
|
||||||
uint16_t base_low;
|
uint16_t base_low;
|
||||||
uint8_t base_mid;
|
uint8_t base_mid;
|
||||||
type type;
|
util::bitset8 type;
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint8_t base_high;
|
uint8_t base_high;
|
||||||
} __attribute__ ((packed, align(8)));
|
} __attribute__ ((packed, align(8)));
|
||||||
@@ -63,5 +62,3 @@ private:
|
|||||||
|
|
||||||
ptr m_ptr;
|
ptr m_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
is_bitfield(GDT::type);
|
|
||||||
|
|||||||
@@ -126,8 +126,7 @@ isr_handler(cpu_state *regs)
|
|||||||
// The zero page is always invalid
|
// The zero page is always invalid
|
||||||
if (cr2 > mem::frame_size) {
|
if (cr2 > mem::frame_size) {
|
||||||
bool user = cr2 < mem::kernel_offset;
|
bool user = cr2 < mem::kernel_offset;
|
||||||
vm_space::fault_type ft =
|
util::bitset8 ft = regs->errorcode;
|
||||||
static_cast<vm_space::fault_type>(regs->errorcode);
|
|
||||||
|
|
||||||
vm_space &space = user
|
vm_space &space = user
|
||||||
? obj::process::current().space()
|
? obj::process::current().space()
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ kernel_main(bootproto::args *args)
|
|||||||
bsp_late_init();
|
bsp_late_init();
|
||||||
|
|
||||||
using bootproto::boot_flags;
|
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);
|
syscall_initialize(enable_test);
|
||||||
|
|
||||||
device_manager &devices = device_manager::get();
|
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();
|
vm_space &space = p->space();
|
||||||
for (const auto § : program.sections) {
|
for (const auto § : program.sections) {
|
||||||
vm_flags flags =
|
util::bitset32 flags = util::bitset32::of(vm_flags::exact);
|
||||||
((sect.type && section_flags::execute) ? vm_flags::exec : vm_flags::none) |
|
if (sect.type.get(section_flags::execute))
|
||||||
((sect.type && section_flags::write) ? vm_flags::write : vm_flags::none);
|
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);
|
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);
|
uint64_t iopl = (3ull << 12);
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ extern "C" {
|
|||||||
|
|
||||||
using bootproto::allocation_register;
|
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,
|
// These objects are initialized _before_ global constructors are called,
|
||||||
// so we don't want them to have global constructors at all, lest they
|
// 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::buffers_offset,
|
||||||
mem::kernel_buffer_pages,
|
mem::kernel_buffer_pages,
|
||||||
mem::buffers_size,
|
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); }
|
||||||
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
|
// Create the heap space and heap allocator
|
||||||
obj::vm_area *heap = new (&g_kernel_heap_area)
|
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 *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::heap_offset, heap, vm_flag_exact);
|
||||||
vm.add(mem::heapmap_offset, heap_map, vm_flags::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};
|
new (&g_kernel_heap) heap_allocator {mem::heap_offset, mem::heap_size, mem::heapmap_offset};
|
||||||
|
|
||||||
// Set up the log area and logger
|
// Set up the log area and logger
|
||||||
size_t log_buffer_size = log::log_pages * arch::frame_size;
|
size_t log_buffer_size = log::log_pages * arch::frame_size;
|
||||||
obj::vm_area *logs = new (&g_kernel_log_area)
|
obj::vm_area *logs = new (&g_kernel_log_area)
|
||||||
obj::vm_area_ring(log_buffer_size, vm_flags::write);
|
obj::vm_area_ring(log_buffer_size, vm_flag_write);
|
||||||
vm.add(mem::logs_offset, logs, vm_flags::exact);
|
vm.add(mem::logs_offset, logs, vm_flag_exact);
|
||||||
|
|
||||||
new (&g_logger) log::logger(
|
new (&g_logger) log::logger(
|
||||||
util::buffer::from(mem::logs_offset, log_buffer_size));
|
util::buffer::from(mem::logs_offset, log_buffer_size));
|
||||||
|
|
||||||
// Set up the capability tables
|
// Set up the capability tables
|
||||||
obj::vm_area *caps = new (&g_cap_table_area)
|
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};
|
new (&g_cap_table) cap_table {mem::caps_offset};
|
||||||
|
|
||||||
@@ -128,8 +129,8 @@ memory_initialize_pre_ctors(bootproto::args &kargs)
|
|||||||
mem::stacks_offset,
|
mem::stacks_offset,
|
||||||
mem::kernel_stack_pages,
|
mem::kernel_stack_pages,
|
||||||
mem::stacks_size,
|
mem::stacks_size,
|
||||||
vm_flags::write};
|
vm_flag_write};
|
||||||
vm.add(mem::stacks_offset, &g_kernel_stacks, vm_flags::exact);
|
vm.add(mem::stacks_offset, &g_kernel_stacks, vm_flag_exact);
|
||||||
|
|
||||||
// Clean out any remaning bootloader page table entries
|
// Clean out any remaning bootloader page table entries
|
||||||
for (unsigned i = 0; i < arch::kernel_root_index; ++i)
|
for (unsigned i = 0; i < arch::kernel_root_index; ++i)
|
||||||
@@ -140,7 +141,7 @@ void
|
|||||||
memory_initialize_post_ctors(bootproto::args &kargs)
|
memory_initialize_post_ctors(bootproto::args &kargs)
|
||||||
{
|
{
|
||||||
vm_space &vm = vm_space::kernel_space();
|
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(
|
g_frame_allocator.free(
|
||||||
get_physical_page(kargs.page_tables.pointer),
|
get_physical_page(kargs.page_tables.pointer),
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
/// Definition of thread kobject types
|
/// Definition of thread kobject types
|
||||||
|
|
||||||
#include <j6/cap_flags.h>
|
#include <j6/cap_flags.h>
|
||||||
#include <util/enum_bitfields.h>
|
|
||||||
#include <util/linked_list.h>
|
#include <util/linked_list.h>
|
||||||
#include <util/spinlock.h>
|
#include <util/spinlock.h>
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace obj {
|
|||||||
|
|
||||||
using mem::frame_size;
|
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_size {size},
|
||||||
m_flags {flags},
|
m_flags {flags},
|
||||||
m_spaces {m_vector_static, 0, static_size},
|
m_spaces {m_vector_static, 0, static_size},
|
||||||
@@ -62,7 +62,7 @@ vm_area::can_resize(size_t size)
|
|||||||
return true;
|
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},
|
m_start {start},
|
||||||
vm_area {size, flags}
|
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()
|
vm_area_fixed::~vm_area_fixed()
|
||||||
{
|
{
|
||||||
if (m_flags && vm_flags::mmio)
|
if (m_flags.get(vm_flags::mmio))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size_t pages = mem::page_count(m_size);
|
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;
|
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}
|
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},
|
m_mapped {nullptr},
|
||||||
vm_area {size, flags}
|
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_pages {buf_pages + 1}, // Sections are N+1 pages for the leading guard page
|
||||||
m_stacks {start, m_pages*mem::frame_size},
|
m_stacks {start, m_pages*mem::frame_size},
|
||||||
vm_area_open {size, flags}
|
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);
|
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},
|
vm_area_open {size * 2, flags},
|
||||||
m_bufsize {size}
|
m_bufsize {size}
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <j6/cap_flags.h>
|
#include <j6/cap_flags.h>
|
||||||
|
#include <util/bitset.h>
|
||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
#include <util/enum_bitfields.h>
|
|
||||||
|
|
||||||
#include "block_allocator.h"
|
#include "block_allocator.h"
|
||||||
#include "objects/kobject.h"
|
#include "objects/kobject.h"
|
||||||
@@ -17,16 +17,15 @@ class vm_space;
|
|||||||
|
|
||||||
namespace obj {
|
namespace obj {
|
||||||
|
|
||||||
enum class vm_flags : uint32_t
|
enum class vm_flags
|
||||||
{
|
{
|
||||||
#define VM_FLAG(name, v) name = v,
|
#define VM_FLAG(name, v) name = v,
|
||||||
#include <j6/tables/vm_flags.inc>
|
#include <j6/tables/vm_flags.inc>
|
||||||
#undef VM_FLAG
|
#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
|
/// Virtual memory areas allow control over memory allocation
|
||||||
class vm_area :
|
class vm_area :
|
||||||
@@ -40,7 +39,7 @@ public:
|
|||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// \arg size Initial virtual size of the memory area
|
/// \arg size Initial virtual size of the memory area
|
||||||
/// \arg flags Flags for this 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();
|
virtual ~vm_area();
|
||||||
|
|
||||||
@@ -48,7 +47,7 @@ public:
|
|||||||
inline size_t size() const { return m_size; }
|
inline size_t size() const { return m_size; }
|
||||||
|
|
||||||
/// Get the flags set for this area
|
/// 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
|
/// Track that this area was added to a vm_space
|
||||||
/// \arg space The space to add this area to
|
/// \arg space The space to add this area to
|
||||||
@@ -83,7 +82,7 @@ protected:
|
|||||||
bool can_resize(size_t size);
|
bool can_resize(size_t size);
|
||||||
|
|
||||||
size_t m_size;
|
size_t m_size;
|
||||||
vm_flags m_flags;
|
util::bitset32 m_flags;
|
||||||
util::vector<vm_space*> m_spaces;
|
util::vector<vm_space*> m_spaces;
|
||||||
|
|
||||||
// Initial static space for m_spaces - most areas will never grow
|
// 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 start Starting physical address of this area
|
||||||
/// \arg size Size of the physical memory area
|
/// \arg size Size of the physical memory area
|
||||||
/// \arg flags Flags for this 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 ~vm_area_fixed();
|
||||||
|
|
||||||
virtual size_t resize(size_t size) override;
|
virtual size_t resize(size_t size) override;
|
||||||
@@ -122,7 +121,7 @@ public:
|
|||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// \arg size Initial virtual size of the memory area
|
/// \arg size Initial virtual size of the memory area
|
||||||
/// \arg flags Flags for this 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 ~vm_area_open();
|
||||||
|
|
||||||
virtual bool get_page(uintptr_t offset, uintptr_t &phys, bool alloc = true) override;
|
virtual bool get_page(uintptr_t offset, uintptr_t &phys, bool alloc = true) override;
|
||||||
@@ -144,7 +143,7 @@ public:
|
|||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// \arg size Initial virtual size of the memory area
|
/// \arg size Initial virtual size of the memory area
|
||||||
/// \arg flags Flags for this 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 ~vm_area_untracked();
|
||||||
|
|
||||||
virtual bool add_to(vm_space *space) override;
|
virtual bool add_to(vm_space *space) override;
|
||||||
@@ -166,7 +165,7 @@ public:
|
|||||||
uintptr_t start,
|
uintptr_t start,
|
||||||
size_t sec_pages,
|
size_t sec_pages,
|
||||||
size_t size,
|
size_t size,
|
||||||
vm_flags flags);
|
util::bitset32 flags);
|
||||||
|
|
||||||
virtual ~vm_area_guarded();
|
virtual ~vm_area_guarded();
|
||||||
|
|
||||||
@@ -194,7 +193,7 @@ public:
|
|||||||
/// \arg size Virtual size of the ring buffer. Note that
|
/// \arg size Virtual size of the ring buffer. Note that
|
||||||
/// the VMA size will be double this value.
|
/// the VMA size will be double this value.
|
||||||
/// \arg flags Flags for this memory area
|
/// \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 ~vm_area_ring();
|
||||||
|
|
||||||
virtual bool get_page(uintptr_t offset, uintptr_t &phys, bool alloc = true) override;
|
virtual bool get_page(uintptr_t offset, uintptr_t &phys, bool alloc = true) override;
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ free_page_header * page_table::s_page_cache = nullptr;
|
|||||||
util::spinlock page_table::s_lock;
|
util::spinlock page_table::s_lock;
|
||||||
constexpr size_t page_table::entry_sizes[4];
|
constexpr size_t page_table::entry_sizes[4];
|
||||||
|
|
||||||
|
inline constexpr util::bitset64 table_flags = page_flags::present | page_flags::write;
|
||||||
constexpr page_table::flag table_flags =
|
|
||||||
page_table::flag::present |
|
|
||||||
page_table::flag::write;
|
|
||||||
|
|
||||||
|
|
||||||
page_table::iterator::iterator(uintptr_t virt, page_table *pml4) :
|
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<uintptr_t>(table) & ~linear_offset;
|
uintptr_t phys = reinterpret_cast<uintptr_t>(table) & ~linear_offset;
|
||||||
|
|
||||||
uint64_t &parent = entry(l - 1);
|
uint64_t &parent = entry(l - 1);
|
||||||
flag flags = table_flags;
|
util::bitset64 flags = table_flags;
|
||||||
if (m_index[0] < arch::kernel_root_index)
|
if (m_index[0] < arch::kernel_root_index)
|
||||||
flags |= flag::user;
|
flags.set(flag::user);
|
||||||
|
|
||||||
m_table[unsigned(l)] = table;
|
m_table[unsigned(l)] = table;
|
||||||
parent = (phys & ~0xfffull) | flags;
|
parent = (phys & ~0xfffull) | flags;
|
||||||
|
|||||||
@@ -4,11 +4,33 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <arch/memory.h>
|
#include <arch/memory.h>
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/bitset.h>
|
||||||
#include <util/spinlock.h>
|
#include <util/spinlock.h>
|
||||||
|
|
||||||
struct free_page_header;
|
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 to allow easy accessing of a memory page being used as a page table.
|
||||||
struct page_table
|
struct page_table
|
||||||
{
|
{
|
||||||
@@ -16,27 +38,19 @@ struct page_table
|
|||||||
enum class level : unsigned { pml4, pdp, pd, pt, page };
|
enum class level : unsigned { pml4, pdp, pd, pt, page };
|
||||||
|
|
||||||
/// Page entry flags
|
/// Page entry flags
|
||||||
enum class flag : uint64_t
|
enum class flag
|
||||||
{
|
{
|
||||||
none = 0x0000,
|
present = 0, /// Entry is present in the table
|
||||||
present = 0x0001, /// Entry is present in the table
|
write = 1, /// Section may be written
|
||||||
write = 0x0002, /// Section may be written
|
user = 2, /// User-accessible
|
||||||
user = 0x0004, /// User-accessible
|
pat0 = 3, /// PAT selector bit 0
|
||||||
pat0 = 0x0008, /// PAT selector bit 0
|
pat1 = 4, /// PAT selector bit 1
|
||||||
pat1 = 0x0010, /// PAT selector bit 1
|
accessed = 5, /// Entry has been accessed
|
||||||
accessed = 0x0020, /// Entry has been accessed
|
dirty = 6, /// Page has been written to
|
||||||
dirty = 0x0040, /// Page has been written to
|
page = 7, /// Entry is a large page
|
||||||
page = 0x0080, /// Entry is a large page
|
pat2 = 7, /// PAT selector bit 2 on PT entries
|
||||||
pat2 = 0x0080, /// PAT selector bit 2 on PT entries
|
global = 8, /// Entry is not PCID-specific
|
||||||
global = 0x0100, /// Entry is not PCID-specific
|
pat2_lg = 12, /// PAT selector bit 2 on large/huge pages
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Helper for getting the next level value
|
/// 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; }
|
||||||
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);
|
|
||||||
|
|||||||
@@ -339,5 +339,5 @@ scheduler::maybe_schedule(TCB *t)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
current_cpu().apic->send_ipi(
|
current_cpu().apic->send_ipi(
|
||||||
lapic::ipi::fixed, isr::ipiSchedule, cpu->id);
|
lapic::ipi_fixed, isr::ipiSchedule, cpu->id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,8 +57,11 @@ start(cpu_data &bsp, void *kpml4)
|
|||||||
// Copy the startup code somwhere the real mode trampoline can run
|
// Copy the startup code somwhere the real mode trampoline can run
|
||||||
uintptr_t addr = 0x8000; // TODO: find a valid address, rewrite addresses
|
uintptr_t addr = 0x8000; // TODO: find a valid address, rewrite addresses
|
||||||
isr vector = static_cast<isr>(addr >> 12);
|
isr vector = static_cast<isr>(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(
|
memcpy(
|
||||||
reinterpret_cast<void*>(addr),
|
reinterpret_cast<void*>(addr),
|
||||||
reinterpret_cast<void*>(&ap_startup),
|
reinterpret_cast<void*>(&ap_startup),
|
||||||
@@ -67,7 +70,7 @@ start(cpu_data &bsp, void *kpml4)
|
|||||||
size_t free_stack_count = 0;
|
size_t free_stack_count = 0;
|
||||||
|
|
||||||
lapic &apic = *bsp.apic;
|
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<isr>(0));
|
apic.send_ipi_broadcast(mode, false, static_cast<isr>(0));
|
||||||
|
|
||||||
for (uint8_t id : ids) {
|
for (uint8_t id : ids) {
|
||||||
@@ -90,7 +93,7 @@ start(cpu_data &bsp, void *kpml4)
|
|||||||
size_t current_count = ap_startup_count;
|
size_t current_count = ap_startup_count;
|
||||||
log::verbose(logs::boot, "Starting AP %d: stack %llx", cpu->index, stack_end);
|
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);
|
apic.send_ipi(startup, vector, id);
|
||||||
for (unsigned i = 0; i < 20; ++i) {
|
for (unsigned i = 0; i < 20; ++i) {
|
||||||
|
|||||||
@@ -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
|
// TODO: check to see if frames are already used? How would that collide with
|
||||||
// the bootloader's allocated pages already being marked used?
|
// 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));
|
frame_allocator::get().used(phys, mem::page_count(size));
|
||||||
|
|
||||||
vm_flags vmf = (static_cast<vm_flags>(flags) & vm_flags::driver_mask);
|
construct_handle<vm_area_fixed>(area, phys, size, f);
|
||||||
construct_handle<vm_area_fixed>(area, phys, size, vmf);
|
|
||||||
|
|
||||||
return j6_status_ok;
|
return j6_status_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ namespace syscalls {
|
|||||||
j6_status_t
|
j6_status_t
|
||||||
vma_create(j6_handle_t *self, size_t size, uint32_t flags)
|
vma_create(j6_handle_t *self, size_t size, uint32_t flags)
|
||||||
{
|
{
|
||||||
vm_flags f = vm_flags::user_mask & flags;
|
util::bitset32 f = flags & vm_user_mask;
|
||||||
if (util::bits::has(f, vm_flags::ring))
|
if (f.get(vm_flags::ring))
|
||||||
construct_handle<vm_area_ring>(self, size, f);
|
construct_handle<vm_area_ring>(self, size, f);
|
||||||
else
|
else
|
||||||
construct_handle<vm_area_open>(self, size, f);
|
construct_handle<vm_area_open>(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)
|
vma_create_map(j6_handle_t *self, size_t size, uintptr_t *base, uint32_t flags)
|
||||||
{
|
{
|
||||||
vm_area *a = nullptr;
|
vm_area *a = nullptr;
|
||||||
vm_flags f = vm_flags::user_mask & flags;
|
util::bitset32 f = flags & vm_user_mask;
|
||||||
if (util::bits::has(f, vm_flags::ring))
|
if (f.get(vm_flags::ring))
|
||||||
a = construct_handle<vm_area_ring>(self, size, f);
|
a = construct_handle<vm_area_ring>(self, size, f);
|
||||||
else
|
else
|
||||||
a = construct_handle<vm_area_open>(self, size, f);
|
a = construct_handle<vm_area_open>(self, size, f);
|
||||||
@@ -40,7 +40,7 @@ j6_status_t
|
|||||||
vma_map(vm_area *self, process *proc, uintptr_t *base, uint32_t flags)
|
vma_map(vm_area *self, process *proc, uintptr_t *base, uint32_t flags)
|
||||||
{
|
{
|
||||||
vm_space &space = proc ? proc->space() : process::current().space();
|
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);
|
*base = space.add(*base, self, f);
|
||||||
return *base ? j6_status_ok : j6_err_collision;
|
return *base ? j6_status_ok : j6_err_collision;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ vm_space::vm_space() :
|
|||||||
obj::vm_area *sysc = new obj::vm_area_fixed(
|
obj::vm_area *sysc = new obj::vm_area_fixed(
|
||||||
g_sysconf_phys,
|
g_sysconf_phys,
|
||||||
sizeof(system_config),
|
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()
|
vm_space::~vm_space()
|
||||||
@@ -81,7 +81,7 @@ vm_space::kernel_space()
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t
|
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)
|
if (!base)
|
||||||
base = min_auto_address;
|
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();
|
uintptr_t end = base + area->size();
|
||||||
|
|
||||||
//TODO: optimize find/insert
|
//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) {
|
for (size_t i = 0; i < m_areas.count(); ++i) {
|
||||||
const vm_space::area &a = m_areas[i];
|
const vm_space::area &a = m_areas[i];
|
||||||
uintptr_t aend = a.base + a.area->size();
|
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--) {
|
while (count--) {
|
||||||
uint64_t &e = dit.entry(page_table::level::pt);
|
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
|
// TODO: handle clobbering mapping
|
||||||
}
|
}
|
||||||
e = sit.entry(page_table::level::pt);
|
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;
|
return;
|
||||||
|
|
||||||
uintptr_t virt = base + offset;
|
uintptr_t virt = base + offset;
|
||||||
page_table::flag flags =
|
util::bitset64 flags =
|
||||||
page_table::flag::present |
|
page_flags::present |
|
||||||
(m_kernel ? page_table::flag::none : page_table::flag::user) |
|
(m_kernel ? page_flags::none : page_flags::user) |
|
||||||
((vma.flags() && vm_flags::write) ? page_table::flag::write : page_table::flag::none) |
|
(vma.flags().get(vm_flags::write) ? page_flags::write : page_flags::none) |
|
||||||
((vma.flags() && vm_flags::write_combine) ? page_table::flag::wc : page_table::flag::none);
|
(vma.flags().get(vm_flags::write_combine) ? page_flags::wc : page_flags::none);
|
||||||
|
|
||||||
page_table::iterator it {virt, m_pml4};
|
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);
|
uint64_t &entry = it.entry(page_table::level::pt);
|
||||||
entry = (phys + i * frame_size) | flags;
|
entry = (phys + i * frame_size) | flags;
|
||||||
log::spam(logs::paging, "Setting entry for %016llx: %016llx [%04llx]",
|
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;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,11 +247,11 @@ vm_space::clear(const obj::vm_area &vma, uintptr_t offset, size_t count, bool fr
|
|||||||
while (count--) {
|
while (count--) {
|
||||||
uint64_t &e = it.entry(page_table::level::pt);
|
uint64_t &e = it.entry(page_table::level::pt);
|
||||||
uintptr_t phys = e & ~0xfffull;
|
uintptr_t phys = e & ~0xfffull;
|
||||||
|
util::bitset64 flags = e;
|
||||||
|
|
||||||
if (e & page_table::flag::present) {
|
if (flags & page_flags::present) {
|
||||||
uint64_t orig = e;
|
|
||||||
e = 0;
|
e = 0;
|
||||||
if (orig & page_table::flag::accessed) {
|
if (flags & page_flags::accessed) {
|
||||||
auto *addr = reinterpret_cast<const uint8_t *>(it.vaddress());
|
auto *addr = reinterpret_cast<const uint8_t *>(it.vaddress());
|
||||||
asm ( "invlpg %0" :: "m"(*addr) : "memory" );
|
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--) {
|
while (count--) {
|
||||||
uint64_t &e = it.entry(page_table::level::pt);
|
uint64_t &e = it.entry(page_table::level::pt);
|
||||||
uintptr_t phys = e & ~0xfffull;
|
uintptr_t phys = e & ~0xfffull;
|
||||||
|
util::bitset64 flags = e;
|
||||||
|
|
||||||
if (e & page_table::flag::present) {
|
if (flags & page_flags::present) {
|
||||||
uint64_t orig = e;
|
|
||||||
e = locked_page_tag;
|
e = locked_page_tag;
|
||||||
if (orig & page_table::flag::accessed) {
|
if (flags & page_flags::accessed) {
|
||||||
auto *addr = reinterpret_cast<const uint8_t *>(it.vaddress());
|
auto *addr = reinterpret_cast<const uint8_t *>(it.vaddress());
|
||||||
asm ( "invlpg %0" :: "m"(*addr) : "memory" );
|
asm ( "invlpg %0" :: "m"(*addr) : "memory" );
|
||||||
}
|
}
|
||||||
@@ -338,10 +338,10 @@ vm_space::initialize_tcb(TCB &tcb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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
|
// TODO: Handle more fult types
|
||||||
if (fault && fault_type::present)
|
if (fault.get(fault_type::present))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uintptr_t page = (addr & ~0xfffull);
|
uintptr_t page = (addr & ~0xfffull);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <j6/flags.h>
|
#include <j6/flags.h>
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/bitset.h>
|
||||||
#include <util/spinlock.h>
|
#include <util/spinlock.h>
|
||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ public:
|
|||||||
/// \arg area The area to add
|
/// \arg area The area to add
|
||||||
/// \arg flags Flags for the operation (exact, clobber, etc)
|
/// \arg flags Flags for the operation (exact, clobber, etc)
|
||||||
/// \returns The base address the area was added at
|
/// \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
|
/// Remove a virtual memory area from this address space
|
||||||
/// \arg area The area to remove
|
/// \arg area The area to remove
|
||||||
@@ -88,15 +88,6 @@ public:
|
|||||||
/// Set this space as the current active space
|
/// Set this space as the current active space
|
||||||
void activate() const;
|
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.
|
/// Allocate pages into virtual memory. May allocate less than requested.
|
||||||
/// \arg virt The virtual address at which to allocate
|
/// \arg virt The virtual address at which to allocate
|
||||||
/// \arg count The number of pages to allocate
|
/// \arg count The number of pages to allocate
|
||||||
@@ -104,11 +95,13 @@ public:
|
|||||||
/// \returns The number of pages actually allocated
|
/// \returns The number of pages actually allocated
|
||||||
size_t allocate(uintptr_t virt, size_t count, uintptr_t *phys);
|
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.
|
/// Handle a page fault.
|
||||||
/// \arg addr Address which caused the fault
|
/// \arg addr Address which caused the fault
|
||||||
/// \arg ft Flags from the interrupt about the kind of fault
|
/// \arg ft Flags from the interrupt about the kind of fault
|
||||||
/// \returns True if the fault was successfully handled
|
/// \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.
|
/// Set up a TCB to operate in this address space.
|
||||||
void initialize_tcb(TCB &tcb);
|
void initialize_tcb(TCB &tcb);
|
||||||
@@ -155,6 +148,4 @@ private:
|
|||||||
util::vector<area> m_areas;
|
util::vector<area> m_areas;
|
||||||
|
|
||||||
util::spinlock m_lock;
|
util::spinlock m_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
is_bitfield(vm_space::fault_type);
|
|
||||||
@@ -3,15 +3,9 @@
|
|||||||
/// Data structures for reading jsix_boot.dat
|
/// Data structures for reading jsix_boot.dat
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <util/enum_bitfields.h>
|
|
||||||
|
|
||||||
namespace bootproto {
|
namespace bootproto {
|
||||||
|
|
||||||
enum class desc_flags : uint16_t {
|
enum class desc_flags { graphical, panic, symbols };
|
||||||
graphical = 0x0001,
|
|
||||||
panic = 0x0002,
|
|
||||||
symbols = 0x0004,
|
|
||||||
};
|
|
||||||
is_bitfield(desc_flags);
|
|
||||||
|
|
||||||
} // namespace bootproto
|
} // namespace bootproto
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <util/bitset.h>
|
||||||
#include <util/counted.h>
|
#include <util/counted.h>
|
||||||
#include <util/enum_bitfields.h>
|
|
||||||
|
|
||||||
namespace bootproto {
|
namespace bootproto {
|
||||||
|
|
||||||
@@ -18,19 +18,13 @@ constexpr uint64_t header_magic = 0x4c454e52454b366aull; // 'j6KERNEL'
|
|||||||
constexpr uint16_t header_version = 2;
|
constexpr uint16_t header_version = 2;
|
||||||
constexpr uint16_t min_header_version = 2;
|
constexpr uint16_t min_header_version = 2;
|
||||||
|
|
||||||
enum class section_flags : uint32_t {
|
enum class section_flags { none, execute, write, read };
|
||||||
none = 0,
|
|
||||||
execute = 1,
|
|
||||||
write = 2,
|
|
||||||
read = 4,
|
|
||||||
};
|
|
||||||
is_bitfield(section_flags);
|
|
||||||
|
|
||||||
struct program_section {
|
struct program_section {
|
||||||
uintptr_t phys_addr;
|
uintptr_t phys_addr;
|
||||||
uintptr_t virt_addr;
|
uintptr_t virt_addr;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
section_flags type;
|
util::bitset32 type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct program {
|
struct program {
|
||||||
@@ -112,18 +106,13 @@ struct frame_block
|
|||||||
uint64_t *bitmap;
|
uint64_t *bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class boot_flags : uint16_t {
|
enum class boot_flags { none, debug, test };
|
||||||
none = 0x0000,
|
|
||||||
debug = 0x0001,
|
|
||||||
test = 0x0002,
|
|
||||||
};
|
|
||||||
is_bitfield(boot_flags);
|
|
||||||
|
|
||||||
struct args
|
struct args
|
||||||
{
|
{
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint16_t version;
|
uint16_t version;
|
||||||
boot_flags flags;
|
util::bitset16 flags;
|
||||||
|
|
||||||
void *pml4;
|
void *pml4;
|
||||||
util::counted<void> page_tables;
|
util::counted<void> page_tables;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ enum class feature {
|
|||||||
max
|
max
|
||||||
};
|
};
|
||||||
|
|
||||||
using features = util::bitset<(unsigned)feature::max>;
|
using features = util::sized_bitset<(unsigned)feature::max>;
|
||||||
|
|
||||||
class cpu_id
|
class cpu_id
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <util/enum_bitfields.h>
|
#include <util/bitset.h>
|
||||||
|
|
||||||
namespace elf {
|
namespace elf {
|
||||||
|
|
||||||
@@ -54,19 +54,12 @@ struct file_header
|
|||||||
|
|
||||||
|
|
||||||
enum class segment_type : uint32_t { null, load, dynamic, interpreter, note };
|
enum class segment_type : uint32_t { null, load, dynamic, interpreter, note };
|
||||||
enum class segment_flags : uint32_t
|
enum class segment_flags { exec, write, read };
|
||||||
{
|
|
||||||
none = 0x00,
|
|
||||||
exec = 0x01,
|
|
||||||
write = 0x02,
|
|
||||||
read = 0x04,
|
|
||||||
};
|
|
||||||
is_bitfield(segment_flags);
|
|
||||||
|
|
||||||
struct segment_header
|
struct segment_header
|
||||||
{
|
{
|
||||||
segment_type type;
|
segment_type type;
|
||||||
segment_flags flags;
|
util::bitset32 flags;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
|
|
||||||
uint64_t vaddr;
|
uint64_t vaddr;
|
||||||
@@ -80,18 +73,13 @@ struct segment_header
|
|||||||
|
|
||||||
|
|
||||||
enum class section_type : uint32_t { null, progbits };
|
enum class section_type : uint32_t { null, progbits };
|
||||||
enum class section_flags : uint64_t
|
enum class section_flags { write, alloc, exec };
|
||||||
{
|
|
||||||
write = 0x01,
|
|
||||||
alloc = 0x02,
|
|
||||||
exec = 0x04,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct section_header
|
struct section_header
|
||||||
{
|
{
|
||||||
uint32_t name_offset;
|
uint32_t name_offset;
|
||||||
section_type type;
|
section_type type;
|
||||||
section_flags flags;
|
util::bitset64 flags;
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
@@ -102,5 +90,3 @@ struct section_header
|
|||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
} // namespace elf
|
} // namespace elf
|
||||||
|
|
||||||
is_bitfield(elf::section_flags);
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
/// Enums used as flags for syscalls
|
/// Enums used as flags for syscalls
|
||||||
|
|
||||||
enum j6_vm_flags {
|
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 <j6/tables/vm_flags.inc>
|
#include <j6/tables/vm_flags.inc>
|
||||||
#undef VM_FLAG
|
#undef VM_FLAG
|
||||||
j6_vm_flag_MAX
|
j6_vm_flag_MAX
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
VM_FLAG( none, 0x00000000 )
|
VM_FLAG( write, 0 )
|
||||||
|
VM_FLAG( exec, 1 )
|
||||||
|
|
||||||
VM_FLAG( write, 0x00000001 )
|
VM_FLAG( contiguous, 4 )
|
||||||
VM_FLAG( exec, 0x00000002 )
|
VM_FLAG( large_pages, 5 )
|
||||||
|
VM_FLAG( huge_pages, 6 )
|
||||||
|
|
||||||
VM_FLAG( contiguous, 0x00000010 )
|
VM_FLAG( write_combine, 8 )
|
||||||
VM_FLAG( large_pages, 0x00000020 )
|
|
||||||
VM_FLAG( huge_pages, 0x00000040 )
|
|
||||||
|
|
||||||
VM_FLAG( write_combine, 0x00000100 )
|
VM_FLAG( mmio, 12 )
|
||||||
|
|
||||||
VM_FLAG( mmio, 0x00001000 )
|
VM_FLAG( exact, 16 )
|
||||||
|
VM_FLAG( ring, 17 )
|
||||||
VM_FLAG( exact, 0x00010000 )
|
|
||||||
VM_FLAG( ring, 0x00020000 )
|
|
||||||
@@ -7,34 +7,148 @@
|
|||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
/// A statically-sized templated bitset
|
/// A statically-sized templated bitset
|
||||||
template <unsigned N>
|
template <typename I>
|
||||||
class bitset
|
class bitset
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using storage_type = I;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
static constexpr storage_type bit_or(T b) { return 1ull << uint64_t(b); }
|
||||||
|
|
||||||
|
template <typename T, typename ...Args>
|
||||||
|
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<I> &o) : m_bits {o.m_bits} {}
|
||||||
|
|
||||||
|
template <typename ...Args>
|
||||||
|
__attribute__ ((always_inline))
|
||||||
|
static constexpr bitset of(Args... args) { return {bit_or(args...)}; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__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 <typename T>
|
||||||
|
__attribute__ ((always_inline))
|
||||||
|
inline constexpr bool get(T i) const {
|
||||||
|
return m_bits & bit(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__attribute__ ((always_inline))
|
||||||
|
inline bitset & set(T i) {
|
||||||
|
m_bits |= bit(i);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__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 <typename T>
|
||||||
|
__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 <typename T>
|
||||||
|
__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 <typename T>
|
||||||
|
__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 <typename T>
|
||||||
|
__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 <typename T>
|
||||||
|
__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 <typename T>
|
||||||
|
inline constexpr storage_type bit(T i) const { return (storage_type(1) << int(i)); }
|
||||||
|
|
||||||
|
storage_type m_bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
using bitset64 = bitset<uint64_t>;
|
||||||
|
using bitset32 = bitset<uint32_t>;
|
||||||
|
using bitset16 = bitset<uint16_t>;
|
||||||
|
using bitset8 = bitset<uint8_t>;
|
||||||
|
|
||||||
|
template <unsigned N>
|
||||||
|
class sized_bitset
|
||||||
{
|
{
|
||||||
static constexpr unsigned num_elems = (N + 63) / 64;
|
static constexpr unsigned num_elems = (N + 63) / 64;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__ ((force_inline))
|
__attribute__ ((always_inline))
|
||||||
inline bool get(T i) const {
|
inline bool get(T i) const {
|
||||||
return bits(i) & bit(i);
|
return bits(i) & bit(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__ ((force_inline))
|
__attribute__ ((always_inline))
|
||||||
inline bitset & set(T i) {
|
inline sized_bitset & set(T i) {
|
||||||
bits(i) |= bit(i);
|
bits(i) |= bit(i);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__ ((force_inline))
|
__attribute__ ((always_inline))
|
||||||
inline bitset & clear(T i) {
|
inline sized_bitset & clear(T i) {
|
||||||
bits(i) &= ~bit(i);
|
bits(i) &= ~bit(i);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__ ((force_inline))
|
__attribute__ ((always_inline))
|
||||||
inline bool operator[](T i) const { return get(i); }
|
inline bool operator[](T i) const { return get(i); }
|
||||||
|
|
||||||
inline bool empty() const {
|
inline bool empty() const {
|
||||||
@@ -45,260 +159,18 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__ ((force_inline))
|
__attribute__ ((always_inline))
|
||||||
inline uint64_t bit(T i) const { return (1ull << (static_cast<uint64_t>(i) & 63)); }
|
inline uint64_t bit(T i) const { return (1ull << (static_cast<uint64_t>(i) & 63)); }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__ ((force_inline))
|
__attribute__ ((always_inline))
|
||||||
inline uint64_t &bits(T i) { return m_bits[static_cast<uint64_t>(i) >> 6]; }
|
inline uint64_t &bits(T i) { return m_bits[static_cast<uint64_t>(i) >> 6]; }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
__attribute__ ((force_inline))
|
__attribute__ ((always_inline))
|
||||||
inline uint64_t bits(T i) const { return m_bits[static_cast<uint64_t>(i) >> 6]; }
|
inline uint64_t bits(T i) const { return m_bits[static_cast<uint64_t>(i) >> 6]; }
|
||||||
|
|
||||||
uint64_t m_bits[num_elems] = {0};
|
uint64_t m_bits[num_elems] = {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A statically-sized templated bitset
|
|
||||||
template <>
|
|
||||||
class bitset<64>
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
static constexpr uint64_t bit_or(T b) { return 1ull << uint64_t(b); }
|
|
||||||
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
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 <typename ...Args>
|
|
||||||
constexpr explicit bitset(Args... args) : m_bits(bit_or(args...)) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & operator=(T v) { m_bits = static_cast<uint64_t>(v); return *this; }
|
|
||||||
|
|
||||||
inline constexpr operator const uint64_t () const { return m_bits; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline constexpr bool get(T i) const {
|
|
||||||
return m_bits & bit(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & set(T i) {
|
|
||||||
m_bits |= bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & clear(T i) {
|
|
||||||
m_bits &= ~bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__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 <typename T>
|
|
||||||
inline constexpr uint64_t bit(T i) const { return (1ull << static_cast<uint64_t>(i)); }
|
|
||||||
|
|
||||||
uint64_t m_bits;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A statically-sized templated bitset
|
|
||||||
template <>
|
|
||||||
class bitset<32>
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
static constexpr uint32_t bit_or(T b) { return 1u << uint32_t(b); }
|
|
||||||
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
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 <typename ...Args>
|
|
||||||
constexpr bitset(Args... args) : m_bits(bit_or(args...)) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bitset & operator=(T v) { m_bits = static_cast<uint32_t>(v); return *this; }
|
|
||||||
|
|
||||||
inline constexpr operator uint32_t () const { return m_bits; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline constexpr bool get(T i) const {
|
|
||||||
return m_bits & bit(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & set(T i) {
|
|
||||||
m_bits |= bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & clear(T i) {
|
|
||||||
m_bits &= ~bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__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 <typename T>
|
|
||||||
inline uint32_t bit(T i) const { return (1u << static_cast<uint32_t>(i)); }
|
|
||||||
|
|
||||||
uint32_t m_bits;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A statically-sized templated bitset
|
|
||||||
template <>
|
|
||||||
class bitset<16>
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
static constexpr uint16_t bit_or(T b) { return 1u << uint16_t(b); }
|
|
||||||
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
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 <typename ...Args>
|
|
||||||
constexpr bitset(Args... args) : m_bits(bit_or(args...)) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bitset & operator=(T v) { m_bits = static_cast<uint16_t>(v); return *this; }
|
|
||||||
|
|
||||||
inline constexpr operator uint16_t () const { return m_bits; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline constexpr bool get(T i) const {
|
|
||||||
return m_bits & bit(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & set(T i) {
|
|
||||||
m_bits |= bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & clear(T i) {
|
|
||||||
m_bits &= ~bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__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 <typename T>
|
|
||||||
inline uint16_t bit(T i) const { return (1u << static_cast<uint16_t>(i)); }
|
|
||||||
|
|
||||||
uint16_t m_bits;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// A statically-sized templated bitset
|
|
||||||
template <>
|
|
||||||
class bitset<8>
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
static constexpr uint8_t bit_or(T b) { return 1u << uint8_t(b); }
|
|
||||||
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
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 <typename ...Args>
|
|
||||||
constexpr bitset(Args... args) : m_bits(bit_or(args...)) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bitset & operator=(T v) { m_bits = static_cast<uint8_t>(v); return *this; }
|
|
||||||
|
|
||||||
inline constexpr operator uint8_t () const { return m_bits; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline constexpr bool get(T i) const {
|
|
||||||
return m_bits & bit(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & set(T i) {
|
|
||||||
m_bits |= bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__attribute__ ((force_inline))
|
|
||||||
inline bitset & clear(T i) {
|
|
||||||
m_bits &= ~bit(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
__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 <typename T>
|
|
||||||
inline uint8_t bit(T i) const { return (1u << static_cast<uint8_t>(i)); }
|
|
||||||
|
|
||||||
uint8_t m_bits;
|
|
||||||
};
|
|
||||||
|
|
||||||
using bitset64 = bitset<64>;
|
|
||||||
using bitset32 = bitset<32>;
|
|
||||||
using bitset16 = bitset<16>;
|
|
||||||
using bitset8 = bitset<8>;
|
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <util/basic_types.h>
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
namespace bits {
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
constexpr bool is_enum_bitfield(E) { return false; }
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
struct enum_or_int {
|
|
||||||
static constexpr bool value =
|
|
||||||
is_enum_bitfield(typename types::non_const<E>::type{})
|
|
||||||
|| types::is_integral<E>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
struct both_enum_or_int {
|
|
||||||
static constexpr bool value =
|
|
||||||
types::conjunction< enum_or_int<E>, enum_or_int<F> >::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename E, typename R>
|
|
||||||
struct enable_if_bitfield {
|
|
||||||
using enum_t = typename types::non_const<E>::type;
|
|
||||||
using type = typename
|
|
||||||
types::enable_if< is_enum_bitfield(enum_t{}), R >::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
|
||||||
operator |= (E &lhs, F rhs)
|
|
||||||
{
|
|
||||||
return lhs = static_cast<E>(
|
|
||||||
static_cast<typename types::integral<E>::type>(lhs) |
|
|
||||||
static_cast<typename types::integral<F>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
|
||||||
operator &= (E &lhs, F rhs)
|
|
||||||
{
|
|
||||||
return lhs = static_cast<E>(
|
|
||||||
static_cast<typename types::integral<E>::type>(lhs) &
|
|
||||||
static_cast<typename types::integral<F>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
|
||||||
operator ^= (E &lhs, F rhs)
|
|
||||||
{
|
|
||||||
return lhs = static_cast<E>(
|
|
||||||
static_cast<typename types::integral<E>::type>(lhs) ^
|
|
||||||
static_cast<typename types::integral<F>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type
|
|
||||||
operator & (E lhs, F rhs) { return lhs &= rhs; }
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type
|
|
||||||
operator | (E lhs, F rhs) { return lhs |= rhs; }
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type
|
|
||||||
operator ^ (E lhs, F rhs) { return lhs ^= rhs; }
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
constexpr typename enable_if_bitfield<E,E>::type
|
|
||||||
operator ~ (E rhs) { return static_cast<E>(~static_cast<typename types::integral<E>::type>(rhs)); }
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
constexpr typename enable_if_bitfield<E,bool>::type
|
|
||||||
operator ! (E rhs) { return static_cast<typename types::integral<E>::type>(rhs) == 0; }
|
|
||||||
|
|
||||||
/// Override logical-and to mean 'rhs contains all bits in lhs'
|
|
||||||
template <typename E>
|
|
||||||
constexpr typename enable_if_bitfield<E,bool>::type
|
|
||||||
operator && (E rhs, E lhs) { return (rhs & lhs) == lhs; }
|
|
||||||
|
|
||||||
/// Generic 'has' for non-marked bitfields
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr bool has(E set, F flags)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(static_cast<typename types::integral<E>::type>(set) &
|
|
||||||
static_cast<typename types::integral<F>::type>(flags)) ==
|
|
||||||
static_cast<typename types::integral<F>::type>(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace bits
|
|
||||||
} // namespace util
|
|
||||||
|
|
||||||
#define is_bitfield(name) \
|
|
||||||
constexpr bool is_enum_bitfield(name) { return true; } \
|
|
||||||
using namespace ::util::bits;
|
|
||||||
|
|
||||||
@@ -20,7 +20,6 @@ module("util",
|
|||||||
"util/cdb.h",
|
"util/cdb.h",
|
||||||
"util/counted.h",
|
"util/counted.h",
|
||||||
"util/deque.h",
|
"util/deque.h",
|
||||||
"util/enum_bitfields.h",
|
|
||||||
"util/format.h",
|
"util/format.h",
|
||||||
"util/hash.h",
|
"util/hash.h",
|
||||||
"util/linked_list.h",
|
"util/linked_list.h",
|
||||||
|
|||||||
@@ -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
|
// TODO: way to remap VMA as read-only if there's no write flag on
|
||||||
// the segment
|
// the segment
|
||||||
unsigned long flags = j6_vm_flag_exact | j6_vm_flag_write;
|
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;
|
flags |= j6_vm_flag_exec;
|
||||||
|
|
||||||
uintptr_t start = file.base() + seg.offset;
|
uintptr_t start = file.base() + seg.offset;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
/// Data structure for dealing with j6romfs images
|
/// Data structure for dealing with j6romfs images
|
||||||
|
|
||||||
#include <util/counted.h>
|
#include <util/counted.h>
|
||||||
#include <util/enum_bitfields.h>
|
|
||||||
|
|
||||||
namespace j6romfs
|
namespace j6romfs
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
// TODO: way to remap VMA as read-only if there's no write flag on
|
||||||
// the segment
|
// the segment
|
||||||
unsigned long flags = j6_vm_flag_write;
|
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;
|
flags |= j6_vm_flag_exec;
|
||||||
|
|
||||||
uintptr_t start = file.base() + seg.offset;
|
uintptr_t start = file.base() + seg.offset;
|
||||||
|
|||||||
Reference in New Issue
Block a user