[bootproto] Create new bootproto lib

This is a rather large commit that is widely focused on cleaning things
out of the 'junk drawer' that is src/include. Most notably, several
things that were put in there because they needed somewhere where both
the kernel, boot, and init could read them have been moved to a new lib,
'bootproto'.

- Moved kernel_args.h and init_args.h to bootproto as kernel.h and
  init.h, respectively.

- Moved counted.h and pointer_manipulation.h into util, renaming the
  latter to util/pointers.h.

- Created a new src/include/arch for very arch-dependent definitions,
  and moved some kernel_memory.h constants like frame size, page table
  entry count, etc to arch/amd64/memory.h. Also created arch/memory.h
  which detects platform and includes the former.

- Got rid of kernel_memory.h entirely in favor of a new, cog-based
  approach. The new definitions/memory_layout.csv lists memory regions
  in descending order from the top of memory, their sizes, and whether
  they are shared outside the kernel (ie, boot needs to know them). The
  new header bootproto/memory.h exposes the addresses of the shared
  regions, while the kernel's memory.h gains the start and size of all
  the regions. Also renamed the badly-named page-offset area the linear
  area.

- The python build scripts got a few new features: the ability to parse
  the csv mentioned above in a new memory.py module; the ability to add
  dependencies to existing source files (The list of files that I had to
  pull out of the main list just to add them with the dependency on
  memory.h was getting too large. So I put them back into the sources
  list, and added the dependency post-hoc.); and the ability to
  reference 'source_root', 'build_root', and 'module_root' variables in
  .module files.

- Some utility functions that were in the kernel's memory.h got moved to
  util/pointers.h and util/misc.h, and misc.h's byteswap was renamed
  byteswap32 to be more specific.
This commit is contained in:
Justin C. Miller
2022-01-03 17:44:13 -08:00
parent cd9b85b555
commit c1d9b35e7c
71 changed files with 623 additions and 496 deletions

View File

@@ -3,7 +3,7 @@
#include <stddef.h>
#include <stdint.h>
#include <util/misc.h>
#include <util/misc.h> // for byteswap32
#include <enum_bitfields.h>
struct acpi_table_header
@@ -22,7 +22,7 @@ struct acpi_table_header
} __attribute__ ((packed));
#define TABLE_HEADER(signature) \
static constexpr uint32_t type_id = util::byteswap(signature); \
static constexpr uint32_t type_id = util::byteswap32(signature); \
acpi_table_header header;

View File

@@ -3,8 +3,8 @@
#include "clock.h"
#include "interrupts.h"
#include "io.h"
#include "kernel_memory.h"
#include "log.h"
#include "memory.h"
uint64_t lapic::s_ticks_per_us = 0;
@@ -51,7 +51,7 @@ ioapic_write(uint32_t volatile *base, uint8_t reg, uint32_t value)
}
apic::apic(uintptr_t base) :
m_base(memory::to_virtual<uint32_t>(base))
m_base(mem::to_virtual<uint32_t>(base))
{
}

View File

@@ -6,7 +6,6 @@
#include "device_manager.h"
#include "gdt.h"
#include "idt.h"
#include "kernel_memory.h"
#include "log.h"
#include "msr.h"
#include "objects/vm_area.h"

View File

@@ -1,5 +1,7 @@
#include <stddef.h>
#include <stdint.h>
#include <util/misc.h> // for checksum
#include <util/pointers.h>
#include "assert.h"
#include "acpi_tables.h"
@@ -8,7 +10,6 @@
#include "console.h"
#include "device_manager.h"
#include "interrupts.h"
#include "kernel_memory.h"
#include "log.h"
#include "memory.h"
#include "objects/endpoint.h"
@@ -47,7 +48,7 @@ struct acpi2_rsdp
bool
acpi_table_header::validate(uint32_t expected_type) const
{
if (::checksum(this, length) != 0) return false;
if (util::checksum(this, length) != 0) return false;
return !expected_type || (expected_type == type);
}
@@ -75,14 +76,14 @@ device_manager::parse_acpi(const void *root_table)
{
kassert(root_table != 0, "ACPI root table pointer is null.");
const acpi1_rsdp *acpi1 = memory::to_virtual(
const acpi1_rsdp *acpi1 = mem::to_virtual(
reinterpret_cast<const acpi1_rsdp *>(root_table));
for (int i = 0; i < sizeof(acpi1->signature); ++i)
kassert(acpi1->signature[i] == expected_signature[i],
"ACPI RSDP table signature mismatch");
uint8_t sum = checksum(acpi1, sizeof(acpi1_rsdp), 0);
uint8_t sum = util::checksum(acpi1, sizeof(acpi1_rsdp), 0);
kassert(sum == 0, "ACPI 1.0 RSDP checksum mismatch.");
kassert(acpi1->revision > 1, "ACPI 1.0 not supported.");
@@ -90,10 +91,10 @@ device_manager::parse_acpi(const void *root_table)
const acpi2_rsdp *acpi2 =
reinterpret_cast<const acpi2_rsdp *>(acpi1);
sum = checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp));
sum = util::checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp));
kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch.");
load_xsdt(memory::to_virtual(acpi2->xsdt_address));
load_xsdt(mem::to_virtual(acpi2->xsdt_address));
}
const device_manager::apic_nmi *
@@ -142,7 +143,7 @@ device_manager::load_xsdt(const acpi_table_header *header)
size_t num_tables = acpi_table_entries(xsdt, sizeof(void*));
for (size_t i = 0; i < num_tables; ++i) {
const acpi_table_header *header =
memory::to_virtual(xsdt->headers[i]);
mem::to_virtual(xsdt->headers[i]);
put_sig(sig, header->type);
log::debug(logs::device, " Found table %s", sig);
@@ -212,8 +213,8 @@ device_manager::load_apic(const acpi_table_header *header)
switch (type) {
case 0: { // Local APIC
uint8_t uid = read_from<uint8_t>(p+2);
uint8_t id = read_from<uint8_t>(p+3);
uint8_t uid = util::read_from<uint8_t>(p+2);
uint8_t id = util::read_from<uint8_t>(p+3);
m_apic_ids.append(id);
log::debug(logs::device, " Local APIC uid %x id %x", uid, id);
@@ -221,8 +222,8 @@ device_manager::load_apic(const acpi_table_header *header)
break;
case 1: { // I/O APIC
uintptr_t base = read_from<uint32_t>(p+4);
uint32_t base_gsi = read_from<uint32_t>(p+8);
uintptr_t base = util::read_from<uint32_t>(p+4);
uint32_t base_gsi = util::read_from<uint32_t>(p+8);
m_ioapics.emplace(base, base_gsi);
log::debug(logs::device, " IO APIC gsi %x base %x", base_gsi, base);
@@ -231,9 +232,9 @@ device_manager::load_apic(const acpi_table_header *header)
case 2: { // Interrupt source override
irq_override o;
o.source = read_from<uint8_t>(p+3);
o.gsi = read_from<uint32_t>(p+4);
o.flags = read_from<uint16_t>(p+8);
o.source = util::read_from<uint8_t>(p+3);
o.gsi = util::read_from<uint32_t>(p+4);
o.flags = util::read_from<uint16_t>(p+8);
m_overrides.append(o);
log::debug(logs::device, " Intr source override IRQ %d -> %d Pol %d Tri %d",
@@ -243,9 +244,9 @@ device_manager::load_apic(const acpi_table_header *header)
case 4: {// LAPIC NMI
apic_nmi nmi;
nmi.cpu = read_from<uint8_t>(p + 2);
nmi.lint = read_from<uint8_t>(p + 5);
nmi.flags = read_from<uint16_t>(p + 3);
nmi.cpu = util::read_from<uint8_t>(p + 2);
nmi.lint = util::read_from<uint8_t>(p + 5);
nmi.flags = util::read_from<uint16_t>(p + 3);
m_nmis.append(nmi);
log::debug(logs::device, " LAPIC NMI Proc %02x LINT%d Pol %d Tri %d",
@@ -279,7 +280,7 @@ device_manager::load_mcfg(const acpi_table_header *header)
m_pci[i].group = mcfge.group;
m_pci[i].bus_start = mcfge.bus_start;
m_pci[i].bus_end = mcfge.bus_end;
m_pci[i].base = memory::to_virtual<uint32_t>(mcfge.base);
m_pci[i].base = mem::to_virtual<uint32_t>(mcfge.base);
log::debug(logs::device, " Found MCFG entry: base %lx group %d bus %d-%d",
mcfge.base, mcfge.group, mcfge.bus_start, mcfge.bus_end);
@@ -308,7 +309,7 @@ device_manager::load_hpet(const acpi_table_header *header)
log::debug(logs::device, " pci vendor id: %04x", pci_vendor_id);
m_hpets.emplace(hpet->index,
reinterpret_cast<uint64_t*>(hpet->base_address.address + ::memory::page_offset));
reinterpret_cast<uint64_t*>(hpet->base_address.address + mem::linear_offset));
}
void

View File

@@ -1,10 +1,11 @@
#include <bootproto/kernel.h>
#include "assert.h"
#include "frame_allocator.h"
#include "kernel_args.h"
#include "kernel_memory.h"
#include "log.h"
#include "memory.h"
using memory::frame_size;
using mem::frame_size;
frame_allocator &
@@ -14,7 +15,7 @@ frame_allocator::get()
return g_frame_allocator;
}
frame_allocator::frame_allocator(kernel::init::frame_block *frames, size_t count) :
frame_allocator::frame_allocator(bootproto::frame_block *frames, size_t count) :
m_blocks {frames},
m_count {count}
{

View File

@@ -5,16 +5,15 @@
#include <stdint.h>
#include <util/spinlock.h>
namespace kernel {
namespace init {
namespace bootproto {
struct frame_block;
}}
}
/// Allocator for physical memory frames
class frame_allocator
{
public:
using frame_block = kernel::init::frame_block;
using frame_block = bootproto::frame_block;
/// Constructor
/// \arg blocks The bootloader-supplied frame bitmap block list

View File

@@ -1,6 +1,7 @@
#include <stdint.h>
#include <string.h>
#include <util/pointers.h>
#include <util/util.h>
#include "assert.h"
@@ -44,8 +45,8 @@ struct heap_allocator::mem_header
set_next(nullptr);
}
inline mem_header * next() { return mask_pointer(m_next, 0x3f); }
inline mem_header * prev() { return mask_pointer(m_prev, 0x3f); }
inline mem_header * next() { return util::mask_pointer(m_next, 0x3f); }
inline mem_header * prev() { return util::mask_pointer(m_prev, 0x3f); }
inline mem_header * buddy() const {
return reinterpret_cast<mem_header *>(
@@ -155,7 +156,7 @@ heap_allocator::ensure_block(unsigned order)
} else {
mem_header *orig = pop_free(order + 1);
if (orig) {
mem_header *next = offset_pointer(orig, 1 << order);
mem_header *next = util::offset_pointer(orig, 1 << order);
new (next) mem_header(orig, nullptr, order);
orig->set_next(next);

View File

@@ -1,5 +1,3 @@
#include "kernel_memory.h"
#include "assert.h"
#include "device_manager.h"
#include "hpet.h"

View File

@@ -1,7 +1,5 @@
#include <stdint.h>
#include "kernel_memory.h"
#include "printf/printf.h"
#include "assert.h"
#include "cpu.h"
@@ -9,14 +7,16 @@
#include "idt.h"
#include "interrupts.h"
#include "io.h"
#include "memory.h"
#include "objects/process.h"
#include "printf/printf.h"
#include "scheduler.h"
#include "vm_space.h"
static const uint16_t PIC1 = 0x20;
static const uint16_t PIC2 = 0xa0;
constexpr uintptr_t apic_eoi_addr = 0xfee000b0 + ::memory::page_offset;
constexpr uintptr_t apic_eoi_addr = 0xfee000b0 + mem::linear_offset;
extern "C" {
void isr_handler(cpu_state*);
@@ -119,7 +119,7 @@ isr_handler(cpu_state *regs)
uintptr_t cr2 = 0;
__asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2));
bool user = cr2 < memory::kernel_offset;
bool user = cr2 < mem::kernel_offset;
vm_space::fault_type ft =
static_cast<vm_space::fault_type>(regs->errorcode);

View File

@@ -5,7 +5,7 @@ kernel = module("kernel",
default = True,
output = "jsix.elf",
targets = [ "kernel" ],
deps = [ "util", "cpu" ],
deps = [ "util", "cpu", "bootproto" ],
includes = [ "." ],
sources = [
"apic.cpp",
@@ -15,6 +15,7 @@ kernel = module("kernel",
"clock.cpp",
"console.cpp",
"cpprt.cpp",
"cpu.cpp",
"debug.cpp",
"debug.s",
"device_manager.cpp",
@@ -29,6 +30,7 @@ kernel = module("kernel",
"io.cpp",
"log.cpp",
"logger.cpp",
"main.cpp",
"memory.cpp",
"memory_bootstrap.cpp",
"msr.cpp",
@@ -45,6 +47,7 @@ kernel = module("kernel",
"printf/printf.c",
"scheduler.cpp",
"serial.cpp",
"syscall.s",
"syscalls/channel.cpp",
"syscalls/endpoint.cpp",
"syscalls/object.cpp",
@@ -58,14 +61,41 @@ kernel = module("kernel",
])
from glob import glob
definitions = glob('definitions/**/*.def', recursive=True)
sysinc = kernel.add_input("syscalls.inc.cog", deps=definitions)
kernel.add_input("syscall.s", deps=[sysinc])
from os.path import join
layout = join(source_root, "definitions/memory_layout.csv")
definitions = glob('definitions/**/*.def', recursive=True)
sysinc = kernel.add_input("syscalls.inc.cog", deps=definitions)
memh = kernel.add_input("memory.h.cog", deps=[layout])
sysh = kernel.add_input("syscall.h.cog", deps=definitions)
sysc = kernel.add_input("syscall.cpp.cog", deps=definitions + [sysh])
kernel.add_input("main.cpp", deps=[sysh])
kernel.add_input("cpu.cpp", deps=[sysh])
kernel.add_depends(["syscall.s"], [sysinc])
kernel.add_depends(["main.cpp", "cpu.cpp"], [sysh])
kernel.add_depends(["main.cpp", "cpu.cpp"], [sysh])
kernel.add_depends([
"apic.cpp",
"device_manager.cpp",
"frame_allocator.cpp",
"heap_allocator.cpp",
"heap_allocator.h",
"interrupts.cpp",
"log.cpp",
"main.cpp",
"memory_bootstrap.cpp",
"memory.cpp",
"objects/channel.cpp",
"objects/thread.cpp",
"objects/vm_area.cpp",
"page_table.cpp",
"page_tree.cpp",
"syscalls/system.cpp",
"tss.cpp",
"vm_space.cpp",
],
[memh])
kernel.variables['ldflags'] = ["${ldflags}", "-T", "${source_root}/src/kernel/kernel.ld"]

View File

@@ -2,10 +2,9 @@
#include <stdint.h>
#include <string.h>
#include <bootproto/kernel.h>
#include <j6/signals.h>
#include <util/vector.h>
#include <kernel_args.h>
#include <kernel_memory.h>
#include "apic.h"
#include "assert.h"
@@ -19,6 +18,7 @@
#include "interrupts.h"
#include "io.h"
#include "log.h"
#include "memory.h"
#include "msr.h"
#include "objects/channel.h"
#include "objects/event.h"
@@ -36,7 +36,7 @@
#endif
extern "C" {
void kernel_main(kernel::init::args *args);
void kernel_main(bootproto::args *args);
void (*__ctors)(void);
void (*__ctors_end)(void);
void long_ap_startup(cpu_data *cpu);
@@ -45,15 +45,13 @@ extern "C" {
void init_ap_trampoline(void*, cpu_data *, void (*)());
}
using namespace kernel;
volatile size_t ap_startup_count;
static bool scheduler_ready = false;
/// Bootstrap the memory managers.
void memory_initialize_pre_ctors(init::args &kargs);
void memory_initialize_post_ctors(init::args &kargs);
void load_init_server(init::program &program, uintptr_t modules_address);
void memory_initialize_pre_ctors(bootproto::args &kargs);
void memory_initialize_post_ctors(bootproto::args &kargs);
void load_init_server(bootproto::program &program, uintptr_t modules_address);
unsigned start_aps(lapic &apic, const util::vector<uint8_t> &ids, void *kpml4);
@@ -80,11 +78,11 @@ run_constructors()
}
void
kernel_main(init::args *args)
kernel_main(bootproto::args *args)
{
if (args->panic) {
IDT::set_nmi_handler(args->panic->entrypoint);
panic::symbol_table = args->symbol_table | memory::page_offset;
panic::symbol_table = args->symbol_table | mem::linear_offset;
}
init_console();
@@ -108,7 +106,7 @@ kernel_main(init::args *args)
cpu->rsp0 = idle_stack_end;
cpu_early_init(cpu);
kassert(args->magic == init::args_magic,
kassert(args->magic == bootproto::args_magic,
"Bad kernel args magic number");
log::debug(logs::boot, "jsix init args are at: %016lx", args);
@@ -193,8 +191,8 @@ kernel_main(init::args *args)
unsigned
start_aps(lapic &apic, const util::vector<uint8_t> &ids, void *kpml4)
{
using memory::frame_size;
using memory::kernel_stack_pages;
using mem::frame_size;
using mem::kernel_stack_pages;
extern size_t ap_startup_code_size;
extern process &g_kernel_process;

View File

@@ -26,12 +26,3 @@ memcpy(void *dest, const void *src, size_t n)
}
}
uint8_t
checksum(const void *p, size_t len, size_t off)
{
uint8_t sum = 0;
const uint8_t *c = reinterpret_cast<const uint8_t *>(p);
for (int i = off; i < len; ++i) sum += c[i];
return sum;
}

View File

@@ -1,52 +0,0 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
void * operator new (size_t, void *p) noexcept;
/// Allocate from the default allocator.
/// \arg size The size in bytes requested
/// \returns A pointer to the newly allocated memory,
/// or nullptr on error
void * kalloc(size_t size);
/// Free memory allocated by `kalloc`.
/// \arg p Pointer that was returned from a `kalloc` call
void kfree(void *p);
/// Read a value of type T from a location in memory
/// \arg p The location in memory to read
/// \returns The value at the given location cast to T
template <typename T>
inline T read_from(const void *p)
{
return *reinterpret_cast<const T *>(p);
}
/// Get a pointer that's offset from another pointer
/// \arg p The base pointer
/// \arg n The offset in bytes
/// \returns The offset pointer
template <typename T>
inline T * offset_pointer(T *p, ptrdiff_t n)
{
return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(p) + n);
}
/// Return a pointer with the given bits masked out
/// \arg p The original pointer
/// \arg mask A bitmask of bits to clear from p
/// \returns The masked pointer
template <typename T>
inline T* mask_pointer(T *p, uintptr_t mask)
{
return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(p) & ~mask);
}
/// Do a simple byte-wise checksum of an area of memory.
/// \arg p The start of the memory region
/// \arg len The number of bytes in the region
/// \arg off An optional offset into the region
uint8_t checksum(const void *p, size_t len, size_t off = 0);

79
src/kernel/memory.h.cog Normal file
View File

@@ -0,0 +1,79 @@
#pragma once
// vim: ft=cpp
/// \file bootproto/memory.h
/// Import memory layout constants necessary for boot
#include <stddef.h>
#include <stdint.h>
#include <arch/memory.h>
void * operator new (size_t, void *p) noexcept;
/// Allocate from the default allocator.
/// \arg size The size in bytes requested
/// \returns A pointer to the newly allocated memory,
/// or nullptr on error
void * kalloc(size_t size);
/// Free memory allocated by `kalloc`.
/// \arg p Pointer that was returned from a `kalloc` call
void kfree(void *p);
/// Kernel space virtual memory layout
namespace mem {
using arch::frame_size;
using arch::kernel_offset;
/// Max number of pages for a kernel stack
constexpr unsigned kernel_stack_pages = 2;
/// Max number of pages for a kernel buffer
constexpr unsigned kernel_buffer_pages = 16;
/*[[[cog code generation
from os.path import join
from memory import Layout
layout = Layout(join(definitions_path, "memory_layout.csv"))
l = max([len(r.name) for r in layout.regions])
for region in layout.regions:
cog.outl(f"constexpr size_t {region.name:>{l}}_size = {region.size:#14x};")
cog.outl("")
for region in layout.regions:
cog.outl(f"constexpr uintptr_t {region.name:>{l}}_offset = {region.start:#x};")
]]]*/
///[[[end]]]
/// Helper to determine if a physical address can be accessed
/// through the linear_offset area.
constexpr bool linear_mappable(uintptr_t a) { return (a & linear_offset) == 0; }
/// Convert a physical address to a virtual one (in the linear-mapped area)
template <typename T> T * to_virtual(uintptr_t a) {
return reinterpret_cast<T*>(a|linear_offset);
}
/// Convert a physical address to a virtual one (in the linear-mapped area)
template <typename T> T * to_virtual(T *p) {
return to_virtual<T>(reinterpret_cast<uintptr_t>(p));
}
/// Get the number of pages needed for a given number of bytes.
/// \arg bytes The number of bytes desired
/// \returns The number of pages needed to contain the desired bytes
constexpr size_t page_count(size_t bytes) { return ((bytes - 1) >> 12) + 1; }
/// Get the given address, aligned to the next lowest page
constexpr uintptr_t page_align_down(uintptr_t a) { return a & ~(frame_size-1); }
/// Get the given address, aligned to the next page
constexpr uintptr_t page_align_up(uintptr_t a) { return page_align_down(a-1) + frame_size; }
} // namespace mem

View File

@@ -1,8 +1,9 @@
#include <utility>
#include <arch/memory.h>
#include <bootproto/kernel.h>
#include <j6/init.h>
#include <util/no_construct.h>
#include <kernel_args.h>
#include <enum_bitfields.h>
#include "assert.h"
@@ -12,6 +13,7 @@
#include "heap_allocator.h"
#include "io.h"
#include "log.h"
#include "memory.h"
#include "msr.h"
#include "objects/process.h"
#include "objects/thread.h"
@@ -19,18 +21,12 @@
#include "objects/vm_area.h"
#include "vm_space.h"
using memory::heap_start;
using memory::kernel_max_heap;
namespace bootproto {
is_bitfield(section_flags);
}
namespace kernel {
namespace init {
is_bitfield(section_flags);
}}
using kernel::init::allocation_register;
using kernel::init::section_flags;
using namespace kernel;
using bootproto::allocation_register;
using bootproto::section_flags;
extern "C" void initialize_main_thread();
extern "C" uintptr_t initialize_main_user_stack();
@@ -51,9 +47,9 @@ static util::no_construct<vm_area_guarded> __g_kernel_stacks_storage;
vm_area_guarded &g_kernel_stacks = __g_kernel_stacks_storage.value;
vm_area_guarded g_kernel_buffers {
memory::buffers_start,
memory::kernel_buffer_pages,
memory::kernel_max_buffers,
mem::buffers_offset,
mem::kernel_buffer_pages,
mem::buffers_size,
vm_flags::write};
void * operator new(size_t size) { return g_kernel_heap.allocate(size); }
@@ -67,26 +63,26 @@ void kfree(void *p) { return g_kernel_heap.free(p); }
template <typename T>
uintptr_t
get_physical_page(T *p) {
return memory::page_align_down(reinterpret_cast<uintptr_t>(p));
return mem::page_align_down(reinterpret_cast<uintptr_t>(p));
}
void
memory_initialize_pre_ctors(init::args &kargs)
memory_initialize_pre_ctors(bootproto::args &kargs)
{
using kernel::init::frame_block;
using bootproto::frame_block;
page_table *kpml4 = static_cast<page_table*>(kargs.pml4);
new (&g_kernel_heap) heap_allocator {heap_start, kernel_max_heap};
new (&g_kernel_heap) heap_allocator {mem::heap_offset, mem::heap_size};
frame_block *blocks = reinterpret_cast<frame_block*>(memory::bitmap_start);
frame_block *blocks = reinterpret_cast<frame_block*>(mem::bitmap_offset);
new (&g_frame_allocator) frame_allocator {blocks, kargs.frame_blocks.count};
// Mark all the things the bootloader allocated for us as used
allocation_register *reg = kargs.allocations;
while (reg) {
for (auto &alloc : reg->entries)
if (alloc.type != init::allocation_type::none)
if (alloc.type != bootproto::allocation_type::none)
g_frame_allocator.used(alloc.address, alloc.count);
reg = reg->next;
}
@@ -95,27 +91,27 @@ memory_initialize_pre_ctors(init::args &kargs)
vm_space &vm = kp->space();
vm_area *heap = new (&g_kernel_heap_area)
vm_area_untracked(kernel_max_heap, vm_flags::write);
vm_area_untracked(mem::heap_size, vm_flags::write);
vm.add(heap_start, heap);
vm.add(mem::heap_offset, heap);
vm_area *stacks = new (&g_kernel_stacks) vm_area_guarded {
memory::stacks_start,
memory::kernel_stack_pages,
memory::kernel_max_stacks,
mem::stacks_offset,
mem::kernel_stack_pages,
mem::stacks_size,
vm_flags::write};
vm.add(memory::stacks_start, &g_kernel_stacks);
vm.add(mem::stacks_offset, &g_kernel_stacks);
// Clean out any remaning bootloader page table entries
for (unsigned i = 0; i < memory::pml4e_kernel; ++i)
for (unsigned i = 0; i < arch::kernel_root_index; ++i)
kpml4->entries[i] = 0;
}
void
memory_initialize_post_ctors(init::args &kargs)
memory_initialize_post_ctors(bootproto::args &kargs)
{
vm_space &vm = vm_space::kernel_space();
vm.add(memory::buffers_start, &g_kernel_buffers);
vm.add(mem::buffers_offset, &g_kernel_buffers);
g_frame_allocator.free(
get_physical_page(kargs.page_tables.pointer),
@@ -179,7 +175,7 @@ log_mtrrs()
void
load_init_server(init::program &program, uintptr_t modules_address)
load_init_server(bootproto::program &program, uintptr_t modules_address)
{
process *p = new process;
p->add_handle(&system::get());

View File

@@ -1,13 +1,13 @@
#include <string.h>
#include "assert.h"
#include "kernel_memory.h"
#include "memory.h"
#include "objects/channel.h"
#include "objects/vm_area.h"
extern vm_area_guarded g_kernel_buffers;
constexpr size_t buffer_bytes = memory::kernel_buffer_pages * memory::frame_size;
constexpr size_t buffer_bytes = mem::kernel_buffer_pages * mem::frame_size;
channel::channel() :
m_len(0),

View File

@@ -1,4 +1,5 @@
#include <j6/signals.h>
#include <util/pointers.h>
#include "cpu.h"
#include "log.h"
@@ -42,7 +43,7 @@ thread::from_tcb(TCB *tcb)
{
static ptrdiff_t offset =
-1 * static_cast<ptrdiff_t>(offsetof(thread, m_tcb));
return reinterpret_cast<thread*>(offset_pointer(tcb, offset));
return reinterpret_cast<thread*>(util::offset_pointer(tcb, offset));
}
thread & thread::current() { return *current_cpu().thread; }
@@ -196,8 +197,8 @@ thread::add_thunk_user(uintptr_t rip3, uintptr_t rip0, uint64_t flags)
void
thread::setup_kernel_stack()
{
using memory::frame_size;
using memory::kernel_stack_pages;
using mem::frame_size;
using mem::kernel_stack_pages;
static constexpr size_t stack_bytes = kernel_stack_pages * frame_size;
constexpr unsigned null_frame_entries = 2;

View File

@@ -1,12 +1,12 @@
#include "kernel_memory.h"
#include "assert.h"
#include "frame_allocator.h"
#include "memory.h"
#include "objects/vm_area.h"
#include "page_tree.h"
#include "vm_space.h"
using memory::frame_size;
using mem::frame_size;
vm_area::vm_area(size_t size, vm_flags flags) :
m_size {size},
@@ -74,7 +74,7 @@ vm_area_fixed::~vm_area_fixed()
if (m_flags && vm_flags::mmio)
return;
size_t pages = memory::page_count(m_size);
size_t pages = mem::page_count(m_size);
frame_allocator::get().free(m_start, pages);
}
@@ -145,7 +145,7 @@ vm_area_open::get_page(uintptr_t offset, uintptr_t &phys)
vm_area_guarded::vm_area_guarded(uintptr_t start, size_t buf_pages, size_t size, vm_flags flags) :
m_start {start},
m_pages {buf_pages},
m_next {memory::frame_size},
m_next {mem::frame_size},
vm_area_open {size, flags}
{
}
@@ -160,7 +160,7 @@ vm_area_guarded::get_section()
}
uintptr_t addr = m_next;
m_next += (m_pages + 1) * memory::frame_size;
m_next += (m_pages + 1) * mem::frame_size;
return m_start + addr;
}

View File

@@ -9,7 +9,6 @@
#include <util/vector.h>
#include <enum_bitfields.h>
#include "kernel_memory.h"
#include "objects/kobject.h"
class page_tree;

View File

@@ -1,13 +1,14 @@
#include <string.h>
#include <util/pointers.h>
#include "assert.h"
#include "console.h"
#include "frame_allocator.h"
#include "kernel_memory.h"
#include "memory.h"
#include "frame_allocator.h"
#include "page_table.h"
using memory::page_offset;
using mem::frame_size;
using mem::linear_offset;
using level = page_table::level;
free_page_header * page_table::s_page_cache = nullptr;
@@ -123,7 +124,7 @@ page_table::iterator::check_table(level l) const
uint64_t parent = entry(l - 1);
if (parent & 1) {
table(l) = reinterpret_cast<page_table*>(page_offset | (parent & ~0xfffull));
table(l) = reinterpret_cast<page_table*>(linear_offset | (parent & ~0xfffull));
return true;
}
return false;
@@ -138,11 +139,11 @@ page_table::iterator::ensure_table(level l)
if (check_table(l)) return;
page_table *table = page_table::get_table_page();
uintptr_t phys = reinterpret_cast<uintptr_t>(table) & ~page_offset;
uintptr_t phys = reinterpret_cast<uintptr_t>(table) & ~linear_offset;
uint64_t &parent = entry(l - 1);
flag flags = table_flags;
if (m_index[0] < memory::pml4e_kernel)
if (m_index[0] < arch::kernel_root_index)
flags |= flag::user;
m_table[unsigned(l)] = table;
@@ -161,14 +162,14 @@ page_table::get(int i, uint16_t *flags) const
if (flags)
*flags = entry & 0xfffull;
return reinterpret_cast<page_table *>((entry & ~0xfffull) + page_offset);
return reinterpret_cast<page_table *>((entry & ~0xfffull) + linear_offset);
}
void
page_table::set(int i, page_table *p, uint16_t flags)
{
entries[i] =
(reinterpret_cast<uint64_t>(p) - page_offset) |
(reinterpret_cast<uint64_t>(p) - linear_offset) |
(flags & 0xfff);
}
@@ -192,7 +193,7 @@ page_table::get_table_page()
--s_cache_count;
}
memset(page, 0, memory::frame_size);
memset(page, 0, frame_size);
return reinterpret_cast<page_table*>(page);
}
@@ -219,14 +220,14 @@ page_table::fill_table_page_cache()
kassert(phys, "Got physical page 0 as a page table");
free_page_header *start =
memory::to_virtual<free_page_header>(phys);
mem::to_virtual<free_page_header>(phys);
for (int i = 0; i < n - 1; ++i)
offset_pointer(start, i * memory::frame_size)
->next = offset_pointer(start, (i+1) * memory::frame_size);
util::offset_pointer(start, i * frame_size)
->next = util::offset_pointer(start, (i+1) * frame_size);
free_page_header *end =
offset_pointer(start, (n-1) * memory::frame_size);
util::offset_pointer(start, (n-1) * frame_size);
end->next = s_page_cache;
s_page_cache = start;
@@ -238,14 +239,14 @@ void
page_table::free(page_table::level l)
{
unsigned last = l == level::pml4
? memory::pml4e_kernel
: memory::table_entries;
? arch::kernel_root_index
: arch::table_entries;
frame_allocator &fa = frame_allocator::get();
for (unsigned i = 0; i < last; ++i) {
if (!is_present(i)) continue;
if (is_page(l, i)) {
size_t count = memory::page_count(entry_sizes[unsigned(l)]);
size_t count = mem::page_count(entry_sizes[unsigned(l)]);
fa.free(entries[i] & ~0xfffull, count);
} else {
get(i)->free(l + 1);
@@ -261,7 +262,7 @@ page_table::dump(page_table::level lvl, bool recurse)
console *cons = console::get();
cons->printf("\nLevel %d page table @ %lx:\n", lvl, this);
for (int i=0; i<memory::table_entries; ++i) {
for (int i=0; i<arch::table_entries; ++i) {
uint64_t ent = entries[i];
if ((ent & 0x1) == 0)
@@ -275,11 +276,11 @@ page_table::dump(page_table::level lvl, bool recurse)
else
cons->printf(" %3d: %016lx -> Level %d table at %016lx\n",
i, ent, deeper(lvl), (ent & ~0xfffull) + page_offset);
i, ent, deeper(lvl), (ent & ~0xfffull) + linear_offset);
}
if (lvl != level::pt && recurse) {
for (int i=0; i<=memory::table_entries; ++i) {
for (int i=0; i<=arch::table_entries; ++i) {
if (is_large_page(lvl, i))
continue;

View File

@@ -3,9 +3,9 @@
/// Helper structures for dealing with page tables.
#include <stdint.h>
#include <arch/memory.h>
#include <util/spinlock.h>
#include <enum_bitfields.h>
#include <kernel_memory.h>
struct free_page_header;
@@ -173,7 +173,7 @@ struct page_table
/// Print this table to the debug console.
void dump(level lvl = level::pml4, bool recurse = true);
uint64_t entries[memory::table_entries];
uint64_t entries[arch::table_entries];
};

View File

@@ -1,8 +1,9 @@
#include <string.h>
#include <arch/memory.h>
#include "assert.h"
#include "frame_allocator.h"
#include "kernel_memory.h"
#include "page_tree.h"
// Page tree levels map the following parts of an offset. Note the xxx part of
@@ -26,7 +27,7 @@ static_assert(sizeof(page_tree) == 66 * sizeof(uintptr_t));
static constexpr unsigned max_level = 5;
static constexpr unsigned bits_per_level = 6;
inline int level_shift(uint8_t level) { return level * bits_per_level + memory::frame_bits; }
inline int level_shift(uint8_t level) { return level * bits_per_level + arch::frame_bits; }
inline uint64_t level_mask(uint8_t level) { return ~0x3full << level_shift(level); }
inline int index_for(uint64_t off, uint8_t level) { return (off >> level_shift(level)) & 0x3full; }

View File

@@ -1,4 +1,3 @@
#include "pointer_manipulation.h"
#include "symbol_table.h"
namespace panicking {

View File

@@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "counted.h"
#include <util/counted.h>
namespace panicking {
@@ -26,7 +26,7 @@ private:
};
const void *m_data;
counted<entry const> m_entries;
util::counted<entry const> m_entries;
};
} // namespace panicking

View File

@@ -106,7 +106,7 @@ pci_device::pci_device(pci_group &group, uint8_t bus, uint8_t device, uint8_t fu
// Walk the extended capabilities list
uint8_t next = m_base[13] & 0xff;
while (next) {
pci_cap *cap = reinterpret_cast<pci_cap *>(offset_pointer(m_base, next));
pci_cap *cap = reinterpret_cast<pci_cap *>(util::offset_pointer(m_base, next));
next = cap->next;
log::debug(logs::device, " - found PCI cap type %02x", cap->id);

View File

@@ -3,7 +3,7 @@
/// PCI devices and groups
#include <stdint.h>
#include "memory.h"
#include <util/pointers.h>
struct pci_group;
enum class isr : uint8_t;
@@ -126,7 +126,7 @@ struct pci_group
/// \returns A pointer to the memory-mapped configuration registers
inline uint32_t * base_for(uint8_t bus, uint8_t device, uint8_t func)
{
return offset_pointer(base,
return util::offset_pointer(base,
pci_device::bus_addr(bus, device, func) << 12);
}

View File

@@ -13,7 +13,6 @@
#include "gdt.h"
#include "interrupts.h"
#include "io.h"
#include "kernel_memory.h"
#include "log.h"
#include "msr.h"
#include "objects/channel.h"

View File

@@ -5,6 +5,7 @@
#include "device_manager.h"
#include "frame_allocator.h"
#include "log.h"
#include "memory.h"
#include "objects/endpoint.h"
#include "objects/thread.h"
#include "objects/system.h"
@@ -70,7 +71,7 @@ system_map_phys(j6_handle_t handle, j6_handle_t * area, uintptr_t phys, size_t s
// TODO: check to see if frames are already used? How would that collide with
// the bootloader's allocated pages already being marked used?
if (!(flags & vm_flags::mmio))
frame_allocator::get().used(phys, memory::page_count(size));
frame_allocator::get().used(phys, mem::page_count(size));
vm_flags vmf = (static_cast<vm_flags>(flags) & vm_flags::driver_mask);
construct_handle<vm_area_fixed>(area, phys, size, vmf);

View File

@@ -3,8 +3,8 @@
#include "assert.h"
#include "cpu.h"
#include "kernel_memory.h"
#include "log.h"
#include "memory.h"
#include "objects/vm_area.h"
#include "tss.h"
@@ -45,8 +45,8 @@ void
TSS::create_ist_stacks(uint8_t ist_entries)
{
extern vm_area_guarded &g_kernel_stacks;
using memory::frame_size;
using memory::kernel_stack_pages;
using mem::frame_size;
using mem::kernel_stack_pages;
constexpr size_t stack_bytes = kernel_stack_pages * frame_size;
for (unsigned ist = 1; ist < 8; ++ist) {

View File

@@ -1,10 +1,11 @@
#include <string.h>
#include "kernel_memory.h"
#include <arch/memory.h>
#include "assert.h"
#include "frame_allocator.h"
#include "log.h"
#include "memory.h"
#include "objects/process.h"
#include "objects/thread.h"
#include "objects/vm_area.h"
@@ -42,8 +43,8 @@ vm_space::vm_space() :
m_pml4 = page_table::get_table_page();
page_table *kpml4 = kernel_space().m_pml4;
memset(m_pml4, 0, memory::frame_size/2);
for (unsigned i = memory::pml4e_kernel; i < memory::table_entries; ++i)
memset(m_pml4, 0, mem::frame_size/2);
for (unsigned i = arch::kernel_root_index; i < arch::table_entries; ++i)
m_pml4->entries[i] = kpml4->entries[i];
}
@@ -81,7 +82,7 @@ void
vm_space::remove_area(vm_area *area)
{
area->remove_from(this);
clear(*area, 0, memory::page_count(area->size()));
clear(*area, 0, mem::page_count(area->size()));
area->handle_release();
}
@@ -153,7 +154,7 @@ vm_space::copy_from(const vm_space &source, const vm_area &vma)
if (!find_vma(vma, from) || !source.find_vma(vma, from))
return;
size_t count = memory::page_count(vma.size());
size_t count = mem::page_count(vma.size());
page_table::iterator dit {to, m_pml4};
page_table::iterator sit {from, source.m_pml4};
@@ -169,7 +170,7 @@ vm_space::copy_from(const vm_space &source, const vm_area &vma)
void
vm_space::page_in(const vm_area &vma, uintptr_t offset, uintptr_t phys, size_t count)
{
using memory::frame_size;
using mem::frame_size;
util::scoped_lock lock {m_lock};
uintptr_t base = 0;
@@ -197,7 +198,7 @@ vm_space::page_in(const vm_area &vma, uintptr_t offset, uintptr_t phys, size_t c
void
vm_space::clear(const vm_area &vma, uintptr_t offset, size_t count, bool free)
{
using memory::frame_size;
using mem::frame_size;
util::scoped_lock lock {m_lock};
uintptr_t base = 0;
@@ -248,13 +249,13 @@ vm_space::active() const
{
uintptr_t pml4 = 0;
__asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (pml4) );
return memory::to_virtual<page_table>(pml4 & ~0xfffull) == m_pml4;
return mem::to_virtual<page_table>(pml4 & ~0xfffull) == m_pml4;
}
void
vm_space::activate() const
{
constexpr uint64_t phys_mask = ~memory::page_offset & ~0xfffull;
constexpr uint64_t phys_mask = ~mem::linear_offset & ~0xfffull;
uintptr_t p = reinterpret_cast<uintptr_t>(m_pml4) & phys_mask;
__asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (p) );
}
@@ -264,7 +265,7 @@ vm_space::initialize_tcb(TCB &tcb)
{
tcb.pml4 =
reinterpret_cast<uintptr_t>(m_pml4) &
~memory::page_offset;
~mem::linear_offset;
}
bool
@@ -300,8 +301,8 @@ vm_space::copy(vm_space &source, vm_space &dest, const void *from, void *to, siz
// TODO: iterate page mappings and continue copying. For now i'm blindly
// assuming both buffers are fully contained within single pages
memcpy(
memory::to_virtual<void>((*dit & ~0xfffull) | (ito & 0xffful)),
memory::to_virtual<void>((*sit & ~0xfffull) | (ifrom & 0xffful)),
mem::to_virtual<void>((*dit & ~0xfffull) | (ito & 0xffful)),
mem::to_virtual<void>((*sit & ~0xfffull) | (ifrom & 0xffful)),
length);
return length;