[kutil] Make enum bitfields usable in other scopes

Changing the SFINAE/enable_if strategy from a type to a constexpr
function means that it can be defined in other scopes than the functions
themselves, because of function overloading. This lets us put everything
into the kutil::bitfields namespace, and make bitfields out of enums in
other namespaces. Also took the chance to clean up the implementation a
bit.
This commit is contained in:
Justin C. Miller
2021-02-19 20:42:49 -08:00
parent cf22ed57a2
commit f9a967caf7
10 changed files with 101 additions and 147 deletions

View File

@@ -84,7 +84,7 @@ enum class acpi_fadt_flags : uint32_t
hw_reduced_acpi = 0x00100000,
low_pwr_s0_idle = 0x00200000
};
IS_BITFIELD(acpi_fadt_flags);
is_bitfield(acpi_fadt_flags);
struct acpi_fadt
{

View File

@@ -19,23 +19,6 @@ protected:
uint32_t *m_base;
};
enum class ipi : uint32_t
{
// Delivery modes
fixed = 0x0000,
smi = 0x0200,
nmi = 0x0400,
init = 0x0500,
startup = 0x0600,
// Flags
deassert = 0x0000,
assert = 0x4000,
edge = 0x0000, ///< edge-triggered
level = 0x8000, ///< level-triggered
};
IS_BITFIELD(ipi);
/// Controller for processor-local APICs
class lapic :
public apic
@@ -48,6 +31,22 @@ public:
/// Get the local APIC's ID
uint8_t get_id();
enum class ipi : uint32_t
{
// Delivery modes
fixed = 0x0000,
smi = 0x0200,
nmi = 0x0400,
init = 0x0500,
startup = 0x0600,
// Flags
deassert = 0x0000,
assert = 0x4000,
edge = 0x0000, ///< edge-triggered
level = 0x8000, ///< level-triggered
};
/// Send an inter-processor interrupt.
/// \arg mode The sending mode
/// \arg vector The interrupt vector
@@ -144,3 +143,6 @@ private:
uint8_t m_id;
uint8_t m_version;
};
is_bitfield(lapic::ipi);

View File

@@ -34,13 +34,13 @@ GDT::GDT(TSS *tss) :
m_ptr.base = &m_entries[0];
// Kernel CS/SS - always 64bit
set(kern_cs_index, 0, 0xfffff, true, gdt_type::read_write | gdt_type::execute);
set(kern_ss_index, 0, 0xfffff, true, gdt_type::read_write);
set(kern_cs_index, 0, 0xfffff, true, type::read_write | type::execute);
set(kern_ss_index, 0, 0xfffff, true, type::read_write);
// User CS32/SS/CS64 - layout expected by SYSRET
set(user_cs32_index, 0, 0xfffff, false, gdt_type::ring3 | gdt_type::read_write | gdt_type::execute);
set(user_ss_index, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write);
set(user_cs64_index, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write | gdt_type::execute);
set(user_cs32_index, 0, 0xfffff, false, type::ring3 | type::read_write | type::execute);
set(user_ss_index, 0, 0xfffff, true, type::ring3 | type::read_write);
set(user_cs64_index, 0, 0xfffff, true, type::ring3 | type::read_write | type::execute);
set_tss(tss);
}
@@ -63,7 +63,7 @@ GDT::install() const
}
void
GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type)
GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t)
{
m_entries[i].limit_low = limit & 0xffff;
m_entries[i].size = (limit >> 16) & 0xf;
@@ -73,7 +73,7 @@ GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type)
m_entries[i].base_mid = (base >> 16) & 0xff;
m_entries[i].base_high = (base >> 24) & 0xff;
m_entries[i].type = type | gdt_type::system | gdt_type::present;
m_entries[i].type = t | type::system | type::present;
}
struct tss_descriptor
@@ -81,7 +81,7 @@ struct tss_descriptor
uint16_t limit_low;
uint16_t base_00;
uint8_t base_16;
gdt_type type;
GDT::type type;
uint8_t size;
uint8_t base_24;
uint32_t base_32;
@@ -105,10 +105,10 @@ GDT::set_tss(TSS *tss)
tssd.reserved = 0;
tssd.type =
gdt_type::accessed |
gdt_type::execute |
gdt_type::ring3 |
gdt_type::present;
type::accessed |
type::execute |
type::ring3 |
type::present;
kutil::memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor));
}
@@ -141,26 +141,26 @@ GDT::dump(unsigned index) const
gdt[i].limit_low;
cons->printf(" %02d:", i);
if (! bitfield_has(gdt[i].type, gdt_type::present)) {
if (! (gdt[i].type && type::present)) {
cons->puts(" Not Present\n");
continue;
}
cons->printf(" Base %08x limit %05x ", base, limit);
switch (gdt[i].type & gdt_type::ring3) {
case gdt_type::ring3: cons->puts("ring3"); break;
case gdt_type::ring2: cons->puts("ring2"); break;
case gdt_type::ring1: cons->puts("ring1"); break;
switch (gdt[i].type & type::ring3) {
case type::ring3: cons->puts("ring3"); break;
case type::ring2: cons->puts("ring2"); break;
case type::ring1: cons->puts("ring1"); break;
default: cons->puts("ring0"); break;
}
cons->printf(" %s %s %s %s %s %s %s\n",
bitfield_has(gdt[i].type, gdt_type::accessed) ? "A" : " ",
bitfield_has(gdt[i].type, gdt_type::read_write) ? "RW" : " ",
bitfield_has(gdt[i].type, gdt_type::conforming) ? "C" : " ",
bitfield_has(gdt[i].type, gdt_type::execute) ? "EX" : " ",
bitfield_has(gdt[i].type, gdt_type::system) ? "S" : " ",
(gdt[i].type && type::accessed) ? "A" : " ",
(gdt[i].type && type::read_write) ? "RW" : " ",
(gdt[i].type && type::conforming) ? "C" : " ",
(gdt[i].type && type::execute) ? "EX" : " ",
(gdt[i].type && type::system) ? "S" : " ",
(gdt[i].size & 0x80) ? "KB" : " B",
(gdt[i].size & 0x60) == 0x20 ? "64" :
(gdt[i].size & 0x60) == 0x40 ? "32" : "16");

View File

@@ -7,20 +7,6 @@
class TSS;
enum class gdt_type : uint8_t
{
accessed = 0x01,
read_write = 0x02,
conforming = 0x04,
execute = 0x08,
system = 0x10,
ring1 = 0x20,
ring2 = 0x40,
ring3 = 0x60,
present = 0x80
};
IS_BITFIELD(gdt_type);
class GDT
{
public:
@@ -39,8 +25,21 @@ public:
/// \arg index Which entry to print, or -1 for all entries
void dump(unsigned index = -1) const;
enum class type : uint8_t
{
accessed = 0x01,
read_write = 0x02,
conforming = 0x04,
execute = 0x08,
system = 0x10,
ring1 = 0x20,
ring2 = 0x40,
ring3 = 0x60,
present = 0x80
};
private:
void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type);
void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t);
void set_tss(TSS *tss);
struct descriptor
@@ -48,7 +47,7 @@ private:
uint16_t limit_low;
uint16_t base_low;
uint8_t base_mid;
gdt_type type;
type type;
uint8_t size;
uint8_t base_high;
} __attribute__ ((packed, align(8)));
@@ -64,3 +63,5 @@ private:
ptr m_ptr;
};
is_bitfield(GDT::type);

View File

@@ -263,7 +263,7 @@ start_aps(lapic &apic, const kutil::vector<uint8_t> &ids, void *kpml4)
size_t free_stack_count = 0;
uintptr_t stack_area_start = 0;
ipi mode = ipi::init | ipi::level | ipi::assert;
lapic::ipi mode = lapic::ipi::init | lapic::ipi::level | lapic::ipi::assert;
apic.send_ipi_broadcast(mode, false, 0);
for (uint8_t id : ids) {
@@ -301,7 +301,7 @@ start_aps(lapic &apic, const kutil::vector<uint8_t> &ids, void *kpml4)
size_t current_count = ap_startup_count;
log::debug(logs::boot, "Starting AP %d: stack %llx", cpu->index, stack_end);
ipi startup = ipi::startup | ipi::assert;
lapic::ipi startup = lapic::ipi::startup | lapic::ipi::assert;
apic.send_ipi(startup, vector, id);
for (unsigned i = 0; i < 20; ++i) {

View File

@@ -24,6 +24,11 @@ using memory::kernel_max_heap;
using namespace kernel;
namespace kernel {
namespace args {
is_bitfield(section_flags);
}}
extern "C" void initialize_main_thread();
extern "C" uintptr_t initialize_main_user_stack();
@@ -203,8 +208,8 @@ load_simple_process(args::program &program)
for (const auto &sect : program.sections) {
vm_flags flags =
(bitfield_has(sect.type, section_flags::execute) ? vm_flags::exec : vm_flags::none) |
(bitfield_has(sect.type, section_flags::write) ? vm_flags::write : vm_flags::none);
((sect.type && section_flags::execute) ? vm_flags::exec : vm_flags::none) |
((sect.type && section_flags::write) ? vm_flags::write : vm_flags::none);
vm_area *vma = new vm_area_fixed(sect.phys_addr, sect.size, flags);
space.add(sect.virt_addr, vma);

View File

@@ -174,4 +174,4 @@ private:
};
IS_BITFIELD(vm_flags);
is_bitfield(vm_flags);

View File

@@ -194,4 +194,4 @@ 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);
is_bitfield(page_table::flag);

View File

@@ -132,4 +132,4 @@ private:
kutil::spinlock m_lock;
};
IS_BITFIELD(vm_space::fault_type);
is_bitfield(vm_space::fault_type);