[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:
7
configure
vendored
7
configure
vendored
@@ -25,7 +25,12 @@ def generate(output, config, manifest):
|
|||||||
modules[m.name] = m
|
modules[m.name] = m
|
||||||
return m
|
return m
|
||||||
|
|
||||||
glo = {'module': module_init}
|
glo = {
|
||||||
|
"module": module_init,
|
||||||
|
"source_root": root,
|
||||||
|
"built_root": output,
|
||||||
|
"module_root": path,
|
||||||
|
}
|
||||||
code = compile(open(fullpath, 'r').read(), fullpath, "exec")
|
code = compile(open(fullpath, 'r').read(), fullpath, "exec")
|
||||||
|
|
||||||
loc = {}
|
loc = {}
|
||||||
|
|||||||
5
definitions/memory_layout.csv
Normal file
5
definitions/memory_layout.csv
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
linear,64T,shared
|
||||||
|
bitmap,1T,shared
|
||||||
|
heap,64G
|
||||||
|
stacks,64G
|
||||||
|
buffers,64G
|
||||||
|
@@ -187,3 +187,8 @@ class Module:
|
|||||||
s = Source(self.root, path, **kwargs)
|
s = Source(self.root, path, **kwargs)
|
||||||
self.sources.append(s)
|
self.sources.append(s)
|
||||||
return str(s.output)
|
return str(s.output)
|
||||||
|
|
||||||
|
def add_depends(self, paths, deps):
|
||||||
|
for source in self.sources:
|
||||||
|
if source.name in paths:
|
||||||
|
source.add_deps(deps)
|
||||||
|
|||||||
@@ -53,11 +53,14 @@ class Source:
|
|||||||
self.__root = Path(root)
|
self.__root = Path(root)
|
||||||
self.__path = Path(path)
|
self.__path = Path(path)
|
||||||
self.__output = output
|
self.__output = output
|
||||||
self.__deps = deps
|
self.__deps = tuple(deps)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.input
|
return self.input
|
||||||
|
|
||||||
|
def add_deps(self, deps):
|
||||||
|
self.__deps += tuple(deps)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def action(self):
|
def action(self):
|
||||||
suffix = self.__path.suffix
|
suffix = self.__path.suffix
|
||||||
|
|||||||
30
scripts/memory.py
Normal file
30
scripts/memory.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
class Layout:
|
||||||
|
from collections import namedtuple
|
||||||
|
Region = namedtuple("Region", ("name", "start", "size", "shared"))
|
||||||
|
|
||||||
|
sizes = {'G': 1024 ** 3, 'T': 1024 ** 4}
|
||||||
|
|
||||||
|
def __init__(self, path):
|
||||||
|
import csv
|
||||||
|
|
||||||
|
regions = []
|
||||||
|
addr = 1 << 64
|
||||||
|
|
||||||
|
with open(path, newline='') as infile:
|
||||||
|
reader = csv.reader(infile)
|
||||||
|
for row in reader:
|
||||||
|
name, size = row[:2]
|
||||||
|
shared = (len(row) > 2 and "shared" in row[2])
|
||||||
|
|
||||||
|
size, mag = int(size[:-1]), size[-1]
|
||||||
|
|
||||||
|
try:
|
||||||
|
mult = Layout.sizes[mag]
|
||||||
|
except KeyError:
|
||||||
|
raise RuntimeError(f"No magnitude named '{mag}'.")
|
||||||
|
|
||||||
|
size *= mult
|
||||||
|
addr -= size
|
||||||
|
regions.append(Layout.Region(name, addr, size, shared))
|
||||||
|
|
||||||
|
self.regions = tuple(regions)
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#include <uefi/boot_services.h>
|
#include <uefi/boot_services.h>
|
||||||
#include <uefi/types.h>
|
#include <uefi/types.h>
|
||||||
|
|
||||||
|
#include <bootproto/init.h>
|
||||||
|
#include <bootproto/kernel.h>
|
||||||
#include <util/no_construct.h>
|
#include <util/no_construct.h>
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "init_args.h"
|
|
||||||
#include "kernel_args.h"
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
@@ -15,9 +17,9 @@ memory::allocator &g_alloc = __g_alloc_storage.value;
|
|||||||
|
|
||||||
namespace memory {
|
namespace memory {
|
||||||
|
|
||||||
using kernel::init::allocation_register;
|
using bootproto::allocation_register;
|
||||||
using kernel::init::module;
|
using bootproto::module;
|
||||||
using kernel::init::page_allocation;
|
using bootproto::page_allocation;
|
||||||
|
|
||||||
static_assert(sizeof(allocation_register) == page_size);
|
static_assert(sizeof(allocation_register) == page_size);
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ allocator::allocate_module_untyped(size_t size)
|
|||||||
|
|
||||||
++m_modules->count;
|
++m_modules->count;
|
||||||
module *m = m_next_mod;
|
module *m = m_next_mod;
|
||||||
m_next_mod = offset_ptr<module>(m_next_mod, size);
|
m_next_mod = util::offset_pointer(m_next_mod, size);
|
||||||
|
|
||||||
m->mod_length = size;
|
m->mod_length = size;
|
||||||
return m;
|
return m;
|
||||||
|
|||||||
@@ -6,25 +6,24 @@ namespace uefi {
|
|||||||
class boot_services;
|
class boot_services;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace kernel {
|
namespace bootproto {
|
||||||
namespace init {
|
|
||||||
enum class allocation_type : uint8_t;
|
enum class allocation_type : uint8_t;
|
||||||
struct allocation_register;
|
struct allocation_register;
|
||||||
struct module;
|
struct module;
|
||||||
struct modules_page;
|
struct modules_page;
|
||||||
}}
|
}
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
namespace memory {
|
namespace memory {
|
||||||
|
|
||||||
using alloc_type = kernel::init::allocation_type;
|
using alloc_type = bootproto::allocation_type;
|
||||||
|
|
||||||
class allocator
|
class allocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using allocation_register = kernel::init::allocation_register;
|
using allocation_register = bootproto::allocation_register;
|
||||||
using module = kernel::init::module;
|
using module = bootproto::module;
|
||||||
using modules_page = kernel::init::modules_page;
|
using modules_page = bootproto::modules_page;
|
||||||
|
|
||||||
allocator(uefi::boot_services &bs);
|
allocator(uefi::boot_services &bs);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module("boot",
|
|||||||
kind = "exe",
|
kind = "exe",
|
||||||
output = "boot.efi",
|
output = "boot.efi",
|
||||||
targets = [ "boot" ],
|
targets = [ "boot" ],
|
||||||
deps = [ "cpu", "elf", "util" ],
|
deps = [ "cpu", "elf", "util", "bootproto" ],
|
||||||
sources = [
|
sources = [
|
||||||
"allocator.cpp",
|
"allocator.cpp",
|
||||||
"console.cpp",
|
"console.cpp",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "kernel_args.h"
|
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
#include <uefi/protos/loaded_image.h>
|
#include <uefi/protos/loaded_image.h>
|
||||||
#include <uefi/protos/simple_file_system.h>
|
#include <uefi/protos/simple_file_system.h>
|
||||||
|
|
||||||
|
#include <bootproto/kernel.h>
|
||||||
|
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "kernel_args.h"
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ file::open(const wchar_t *path)
|
|||||||
return file(fh);
|
return file(fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer
|
util::buffer
|
||||||
file::load()
|
file::load()
|
||||||
{
|
{
|
||||||
uint8_t info_buf[sizeof(uefi::protos::file_info) + 100];
|
uint8_t info_buf[sizeof(uefi::protos::file_info) + 100];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <uefi/types.h>
|
#include <uefi/types.h>
|
||||||
#include "counted.h"
|
#include <util/counted.h>
|
||||||
|
|
||||||
namespace uefi {
|
namespace uefi {
|
||||||
struct boot_services;
|
struct boot_services;
|
||||||
@@ -29,7 +29,7 @@ public:
|
|||||||
/// Load the contents of this file into memory.
|
/// Load the contents of this file into memory.
|
||||||
/// \returns A buffer describing the loaded memory. The
|
/// \returns A buffer describing the loaded memory. The
|
||||||
/// memory will be page-aligned.
|
/// memory will be page-aligned.
|
||||||
buffer load();
|
util::buffer load();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend file get_boot_volume(uefi::handle, uefi::boot_services*);
|
friend file get_boot_volume(uefi::handle, uefi::boot_services*);
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
#include <uefi/boot_services.h>
|
#include <uefi/boot_services.h>
|
||||||
#include <uefi/types.h>
|
#include <uefi/types.h>
|
||||||
|
|
||||||
|
#include <bootproto/init.h>
|
||||||
|
#include <elf/file.h>
|
||||||
|
#include <elf/headers.h>
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "elf/file.h"
|
|
||||||
#include "elf/headers.h"
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "init_args.h"
|
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "paging.h"
|
#include "paging.h"
|
||||||
#include "pointer_manipulation.h"
|
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
|
|
||||||
namespace init = kernel::init;
|
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
namespace loader {
|
namespace loader {
|
||||||
|
|
||||||
using memory::alloc_type;
|
using memory::alloc_type;
|
||||||
|
|
||||||
buffer
|
util::buffer
|
||||||
load_file(
|
load_file(
|
||||||
fs::file &disk,
|
fs::file &disk,
|
||||||
const program_desc &desc)
|
const program_desc &desc)
|
||||||
@@ -29,7 +28,7 @@ load_file(
|
|||||||
status_line status(L"Loading file", desc.path);
|
status_line status(L"Loading file", desc.path);
|
||||||
|
|
||||||
fs::file file = disk.open(desc.path);
|
fs::file file = disk.open(desc.path);
|
||||||
buffer b = file.load();
|
util::buffer b = file.load();
|
||||||
|
|
||||||
//console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size);
|
//console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size);
|
||||||
return b;
|
return b;
|
||||||
@@ -37,17 +36,17 @@ load_file(
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_module(buffer data, const program_desc &desc, bool loaded)
|
create_module(util::buffer data, const program_desc &desc, bool loaded)
|
||||||
{
|
{
|
||||||
size_t path_len = wstrlen(desc.path);
|
size_t path_len = wstrlen(desc.path);
|
||||||
init::module_program *mod = g_alloc.allocate_module<init::module_program>(path_len);
|
bootproto::module_program *mod = g_alloc.allocate_module<bootproto::module_program>(path_len);
|
||||||
mod->mod_type = init::module_type::program;
|
mod->mod_type = bootproto::module_type::program;
|
||||||
mod->base_address = reinterpret_cast<uintptr_t>(data.pointer);
|
mod->base_address = reinterpret_cast<uintptr_t>(data.pointer);
|
||||||
mod->size = data.count;
|
mod->size = data.count;
|
||||||
if (loaded)
|
if (loaded)
|
||||||
mod->mod_flags = static_cast<init::module_flags>(
|
mod->mod_flags = static_cast<bootproto::module_flags>(
|
||||||
static_cast<uint8_t>(mod->mod_flags) |
|
static_cast<uint8_t>(mod->mod_flags) |
|
||||||
static_cast<uint8_t>(init::module_flags::no_load));
|
static_cast<uint8_t>(bootproto::module_flags::no_load));
|
||||||
|
|
||||||
// TODO: support non-ascii path characters and do real utf-16 to utf-8
|
// TODO: support non-ascii path characters and do real utf-16 to utf-8
|
||||||
// conversion
|
// conversion
|
||||||
@@ -56,7 +55,7 @@ create_module(buffer data, const program_desc &desc, bool loaded)
|
|||||||
mod->filename[path_len] = 0;
|
mod->filename[path_len] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
init::program *
|
bootproto::program *
|
||||||
load_program(
|
load_program(
|
||||||
fs::file &disk,
|
fs::file &disk,
|
||||||
const program_desc &desc,
|
const program_desc &desc,
|
||||||
@@ -64,7 +63,7 @@ load_program(
|
|||||||
{
|
{
|
||||||
status_line status(L"Loading program", desc.name);
|
status_line status(L"Loading program", desc.name);
|
||||||
|
|
||||||
buffer data = load_file(disk, desc);
|
util::buffer data = load_file(disk, desc);
|
||||||
|
|
||||||
if (add_module)
|
if (add_module)
|
||||||
create_module(data, desc, true);
|
create_module(data, desc, true);
|
||||||
@@ -79,20 +78,20 @@ load_program(
|
|||||||
++num_sections;
|
++num_sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
init::program_section *sections = new init::program_section [num_sections];
|
bootproto::program_section *sections = new bootproto::program_section [num_sections];
|
||||||
|
|
||||||
size_t next_section = 0;
|
size_t next_section = 0;
|
||||||
for (auto &seg : program.programs()) {
|
for (auto &seg : program.programs()) {
|
||||||
if (seg.type != elf::segment_type::load)
|
if (seg.type != elf::segment_type::load)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
init::program_section §ion = sections[next_section++];
|
bootproto::program_section §ion = sections[next_section++];
|
||||||
|
|
||||||
size_t page_count = memory::bytes_to_pages(seg.mem_size);
|
size_t page_count = memory::bytes_to_pages(seg.mem_size);
|
||||||
|
|
||||||
if (seg.mem_size > seg.file_size) {
|
if (seg.mem_size > seg.file_size) {
|
||||||
void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true);
|
void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true);
|
||||||
void *source = offset_ptr<void>(data.pointer, seg.offset);
|
void *source = util::offset_pointer(data.pointer, seg.offset);
|
||||||
g_alloc.copy(pages, source, seg.file_size);
|
g_alloc.copy(pages, source, seg.file_size);
|
||||||
section.phys_addr = reinterpret_cast<uintptr_t>(pages);
|
section.phys_addr = reinterpret_cast<uintptr_t>(pages);
|
||||||
} else {
|
} else {
|
||||||
@@ -101,10 +100,10 @@ load_program(
|
|||||||
|
|
||||||
section.virt_addr = seg.vaddr;
|
section.virt_addr = seg.vaddr;
|
||||||
section.size = seg.mem_size;
|
section.size = seg.mem_size;
|
||||||
section.type = static_cast<init::section_flags>(seg.flags);
|
section.type = static_cast<bootproto::section_flags>(seg.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
init::program *prog = new init::program;
|
bootproto::program *prog = new bootproto::program;
|
||||||
prog->sections = { .pointer = sections, .count = num_sections };
|
prog->sections = { .pointer = sections, .count = num_sections };
|
||||||
prog->phys_base = program.base();
|
prog->phys_base = program.base();
|
||||||
prog->entrypoint = program.entrypoint();
|
prog->entrypoint = program.entrypoint();
|
||||||
@@ -118,25 +117,25 @@ load_module(
|
|||||||
{
|
{
|
||||||
status_line status(L"Loading module", desc.name);
|
status_line status(L"Loading module", desc.name);
|
||||||
|
|
||||||
buffer data = load_file(disk, desc);
|
util::buffer data = load_file(disk, desc);
|
||||||
create_module(data, desc, false);
|
create_module(data, desc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
verify_kernel_header(init::program &program)
|
verify_kernel_header(bootproto::program &program)
|
||||||
{
|
{
|
||||||
status_line status(L"Verifying kernel header");
|
status_line status(L"Verifying kernel header");
|
||||||
|
|
||||||
const init::header *header =
|
const bootproto::header *header =
|
||||||
reinterpret_cast<const init::header *>(program.sections[0].phys_addr);
|
reinterpret_cast<const bootproto::header *>(program.sections[0].phys_addr);
|
||||||
|
|
||||||
if (header->magic != init::header_magic)
|
if (header->magic != bootproto::header_magic)
|
||||||
error::raise(uefi::status::load_error, L"Bad kernel magic number");
|
error::raise(uefi::status::load_error, L"Bad kernel magic number");
|
||||||
|
|
||||||
if (header->length < sizeof(init::header))
|
if (header->length < sizeof(bootproto::header))
|
||||||
error::raise(uefi::status::load_error, L"Bad kernel header length");
|
error::raise(uefi::status::load_error, L"Bad kernel header length");
|
||||||
|
|
||||||
if (header->version < init::min_header_version)
|
if (header->version < bootproto::min_header_version)
|
||||||
error::raise(uefi::status::unsupported, L"Kernel header version not supported");
|
error::raise(uefi::status::unsupported, L"Kernel header version not supported");
|
||||||
|
|
||||||
console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n",
|
console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n",
|
||||||
|
|||||||
@@ -2,13 +2,12 @@
|
|||||||
/// Definitions for loading the kernel into memory
|
/// Definitions for loading the kernel into memory
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "counted.h"
|
#include <util/counted.h>
|
||||||
|
|
||||||
namespace kernel {
|
namespace bootproto {
|
||||||
namespace init {
|
|
||||||
struct program;
|
struct program;
|
||||||
struct module;
|
struct module;
|
||||||
}}
|
}
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
|
|
||||||
@@ -27,7 +26,7 @@ struct program_desc
|
|||||||
/// Load a file from disk into memory.
|
/// Load a file from disk into memory.
|
||||||
/// \arg disk The opened UEFI filesystem to load from
|
/// \arg disk The opened UEFI filesystem to load from
|
||||||
/// \arg desc The program descriptor identifying the file
|
/// \arg desc The program descriptor identifying the file
|
||||||
buffer
|
util::buffer
|
||||||
load_file(
|
load_file(
|
||||||
fs::file &disk,
|
fs::file &disk,
|
||||||
const program_desc &desc);
|
const program_desc &desc);
|
||||||
@@ -36,7 +35,7 @@ load_file(
|
|||||||
/// \arg disk The opened UEFI filesystem to load from
|
/// \arg disk The opened UEFI filesystem to load from
|
||||||
/// \arg desc The program descriptor identifying the program
|
/// \arg desc The program descriptor identifying the program
|
||||||
/// \arg add_module Also create a module for this loaded program
|
/// \arg add_module Also create a module for this loaded program
|
||||||
kernel::init::program *
|
bootproto::program *
|
||||||
load_program(
|
load_program(
|
||||||
fs::file &disk,
|
fs::file &disk,
|
||||||
const program_desc &desc,
|
const program_desc &desc,
|
||||||
@@ -53,7 +52,7 @@ load_module(
|
|||||||
/// Verify that a loaded ELF has the j6 kernel header
|
/// Verify that a loaded ELF has the j6 kernel header
|
||||||
/// \arg program The program to check for a header
|
/// \arg program The program to check for a header
|
||||||
void
|
void
|
||||||
verify_kernel_header(kernel::init::program &program);
|
verify_kernel_header(bootproto::program &program);
|
||||||
|
|
||||||
} // namespace loader
|
} // namespace loader
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
|
|||||||
@@ -7,6 +7,11 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <bootproto/kernel.h>
|
||||||
|
#include <bootproto/memory.h>
|
||||||
|
#include <util/counted.h>
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@@ -19,19 +24,13 @@
|
|||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
|
|
||||||
#include "kernel_args.h"
|
|
||||||
|
|
||||||
namespace kernel {
|
|
||||||
#include "kernel_memory.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace init = kernel::init;
|
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
|
|
||||||
const loader::program_desc kern_desc = {L"kernel", L"jsix.elf"};
|
const loader::program_desc kern_desc = {L"kernel", L"jsix.elf"};
|
||||||
const loader::program_desc init_desc = {L"init server", L"srv.init.elf"};
|
const loader::program_desc init_desc = {L"init server", L"srv.init.elf"};
|
||||||
const loader::program_desc fb_driver = {L"UEFI framebuffer driver", L"drv.uefi_fb.elf"};
|
const loader::program_desc fb_driver = {L"UEFI framebuffer driver", L"drv.uefi_fb.elf"};
|
||||||
|
const loader::program_desc uart_driver = {L"Serial port driver", L"drv.uart.elf"};
|
||||||
|
|
||||||
const loader::program_desc panic_handler = {L"Serial panic handler", L"panic.serial.elf"};
|
const loader::program_desc panic_handler = {L"Serial panic handler", L"panic.serial.elf"};
|
||||||
|
|
||||||
@@ -44,13 +43,13 @@ const loader::program_desc extra_programs[] = {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void change_pointer(T *&pointer)
|
void change_pointer(T *&pointer)
|
||||||
{
|
{
|
||||||
pointer = offset_ptr<T>(pointer, kernel::memory::page_offset);
|
pointer = util::offset_pointer(pointer, bootproto::mem::linear_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The main procedure for the portion of the loader that runs while
|
/// The main procedure for the portion of the loader that runs while
|
||||||
/// UEFI is still in control of the machine. (ie, while the loader still
|
/// UEFI is still in control of the machine. (ie, while the loader still
|
||||||
/// has access to boot services.)
|
/// has access to boot services.)
|
||||||
init::args *
|
bootproto::args *
|
||||||
uefi_preboot(uefi::handle image, uefi::system_table *st)
|
uefi_preboot(uefi::handle image, uefi::system_table *st)
|
||||||
{
|
{
|
||||||
uefi::boot_services *bs = st->boot_services;
|
uefi::boot_services *bs = st->boot_services;
|
||||||
@@ -61,11 +60,11 @@ uefi_preboot(uefi::handle image, uefi::system_table *st)
|
|||||||
hw::check_cpu_supported();
|
hw::check_cpu_supported();
|
||||||
memory::init_pointer_fixup(bs, rs);
|
memory::init_pointer_fixup(bs, rs);
|
||||||
|
|
||||||
init::args *args = new init::args;
|
bootproto::args *args = new bootproto::args;
|
||||||
g_alloc.zero(args, sizeof(init::args));
|
g_alloc.zero(args, sizeof(bootproto::args));
|
||||||
|
|
||||||
args->magic = init::args_magic;
|
args->magic = bootproto::args_magic;
|
||||||
args->version = init::args_version;
|
args->version = bootproto::args_version;
|
||||||
args->runtime_services = rs;
|
args->runtime_services = rs;
|
||||||
args->acpi_table = hw::find_acpi_table(st);
|
args->acpi_table = hw::find_acpi_table(st);
|
||||||
memory::mark_pointer_fixup(&args->runtime_services);
|
memory::mark_pointer_fixup(&args->runtime_services);
|
||||||
@@ -77,7 +76,7 @@ uefi_preboot(uefi::handle image, uefi::system_table *st)
|
|||||||
|
|
||||||
/// Load the kernel and other programs from disk
|
/// Load the kernel and other programs from disk
|
||||||
void
|
void
|
||||||
load_resources(init::args *args, video::screen *screen, uefi::handle image, uefi::boot_services *bs)
|
load_resources(bootproto::args *args, video::screen *screen, uefi::handle image, uefi::boot_services *bs)
|
||||||
{
|
{
|
||||||
status_line status {L"Loading programs"};
|
status_line status {L"Loading programs"};
|
||||||
|
|
||||||
@@ -86,9 +85,11 @@ load_resources(init::args *args, video::screen *screen, uefi::handle image, uefi
|
|||||||
if (screen) {
|
if (screen) {
|
||||||
video::make_module(screen);
|
video::make_module(screen);
|
||||||
loader::load_module(disk, fb_driver);
|
loader::load_module(disk, fb_driver);
|
||||||
|
} else {
|
||||||
|
loader::load_module(disk, uart_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer symbol_table = loader::load_file(disk, {L"symbol table", L"symbol_table.dat"});
|
util::buffer symbol_table = loader::load_file(disk, {L"symbol table", L"symbol_table.dat"});
|
||||||
args->symbol_table = reinterpret_cast<uintptr_t>(symbol_table.pointer);
|
args->symbol_table = reinterpret_cast<uintptr_t>(symbol_table.pointer);
|
||||||
|
|
||||||
args->kernel = loader::load_program(disk, kern_desc, true);
|
args->kernel = loader::load_program(disk, kern_desc, true);
|
||||||
@@ -102,7 +103,7 @@ load_resources(init::args *args, video::screen *screen, uefi::handle image, uefi
|
|||||||
}
|
}
|
||||||
|
|
||||||
memory::efi_mem_map
|
memory::efi_mem_map
|
||||||
uefi_exit(init::args *args, uefi::handle image, uefi::boot_services *bs)
|
uefi_exit(bootproto::args *args, uefi::handle image, uefi::boot_services *bs)
|
||||||
{
|
{
|
||||||
status_line status {L"Exiting UEFI", nullptr, false};
|
status_line status {L"Exiting UEFI", nullptr, false};
|
||||||
|
|
||||||
@@ -131,14 +132,14 @@ efi_main(uefi::handle image, uefi::system_table *st)
|
|||||||
uefi::boot_services *bs = st->boot_services;
|
uefi::boot_services *bs = st->boot_services;
|
||||||
console con(st->con_out);
|
console con(st->con_out);
|
||||||
|
|
||||||
init::allocation_register *allocs = nullptr;
|
bootproto::allocation_register *allocs = nullptr;
|
||||||
init::modules_page *modules = nullptr;
|
bootproto::modules_page *modules = nullptr;
|
||||||
memory::allocator::init(allocs, modules, bs);
|
memory::allocator::init(allocs, modules, bs);
|
||||||
|
|
||||||
video::screen *screen = video::pick_mode(bs);
|
video::screen *screen = video::pick_mode(bs);
|
||||||
con.announce();
|
con.announce();
|
||||||
|
|
||||||
init::args *args = uefi_preboot(image, st);
|
bootproto::args *args = uefi_preboot(image, st);
|
||||||
load_resources(args, screen, image, bs);
|
load_resources(args, screen, image, bs);
|
||||||
memory::efi_mem_map map = uefi_exit(args, image, st->boot_services);
|
memory::efi_mem_map map = uefi_exit(args, image, st->boot_services);
|
||||||
|
|
||||||
@@ -153,8 +154,8 @@ efi_main(uefi::handle image, uefi::system_table *st)
|
|||||||
|
|
||||||
memory::fix_frame_blocks(args);
|
memory::fix_frame_blocks(args);
|
||||||
|
|
||||||
init::entrypoint kentry =
|
bootproto::entrypoint kentry =
|
||||||
reinterpret_cast<init::entrypoint>(args->kernel->entrypoint);
|
reinterpret_cast<bootproto::entrypoint>(args->kernel->entrypoint);
|
||||||
//status.next();
|
//status.next();
|
||||||
|
|
||||||
hw::setup_control_regs();
|
hw::setup_control_regs();
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
#include <uefi/runtime_services.h>
|
#include <uefi/runtime_services.h>
|
||||||
#include <uefi/types.h>
|
#include <uefi/types.h>
|
||||||
|
|
||||||
|
#include <bootproto/memory.h>
|
||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "paging.h"
|
#include "paging.h"
|
||||||
@@ -61,7 +62,7 @@ virtualize(void *pml4, efi_mem_map &map, uefi::runtime_services *rs)
|
|||||||
paging::add_current_mappings(reinterpret_cast<paging::page_table*>(pml4));
|
paging::add_current_mappings(reinterpret_cast<paging::page_table*>(pml4));
|
||||||
|
|
||||||
for (auto &desc : map)
|
for (auto &desc : map)
|
||||||
desc.virtual_start = desc.physical_start + ::memory::page_offset;
|
desc.virtual_start = desc.physical_start + bootproto::mem::linear_offset;
|
||||||
|
|
||||||
// Write our new PML4 pointer to CR3
|
// Write our new PML4 pointer to CR3
|
||||||
asm volatile ( "mov %0, %%cr3" :: "r" (pml4) );
|
asm volatile ( "mov %0, %%cr3" :: "r" (pml4) );
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#include <uefi/boot_services.h>
|
#include <uefi/boot_services.h>
|
||||||
#include <uefi/types.h>
|
#include <uefi/types.h>
|
||||||
|
|
||||||
|
#include <bootproto/kernel.h>
|
||||||
|
#include <bootproto/memory.h>
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "paging.h"
|
#include "paging.h"
|
||||||
@@ -12,10 +15,10 @@
|
|||||||
namespace boot {
|
namespace boot {
|
||||||
namespace memory {
|
namespace memory {
|
||||||
|
|
||||||
using kernel::init::frame_block;
|
using bootproto::frame_block;
|
||||||
using kernel::init::frames_per_block;
|
using bootproto::frames_per_block;
|
||||||
using kernel::init::mem_entry;
|
using bootproto::mem_entry;
|
||||||
using kernel::init::mem_type;
|
using bootproto::mem_type;
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -89,7 +92,7 @@ memory_type_name(uefi::memory_type t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const wchar_t *
|
static const wchar_t *
|
||||||
kernel_memory_type_name(kernel::init::mem_type t)
|
kernel_memory_type_name(bootproto::mem_type t)
|
||||||
{
|
{
|
||||||
return kernel_memory_type_names[static_cast<uint32_t>(t)];
|
return kernel_memory_type_names[static_cast<uint32_t>(t)];
|
||||||
}
|
}
|
||||||
@@ -103,7 +106,7 @@ can_merge(mem_entry &prev, mem_type type, uefi::memory_descriptor &next)
|
|||||||
prev.attr == (next.attribute & 0xffffffff);
|
prev.attr == (next.attribute & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
counted<mem_entry>
|
util::counted<mem_entry>
|
||||||
build_kernel_map(efi_mem_map &map)
|
build_kernel_map(efi_mem_map &map)
|
||||||
{
|
{
|
||||||
status_line status {L"Creating kernel memory map"};
|
status_line status {L"Creating kernel memory map"};
|
||||||
@@ -200,8 +203,8 @@ build_kernel_map(efi_mem_map &map)
|
|||||||
inline size_t bitmap_size(size_t frames) { return (frames + 63) / 64; }
|
inline size_t bitmap_size(size_t frames) { return (frames + 63) / 64; }
|
||||||
inline size_t num_blocks(size_t frames) { return (frames + (frames_per_block-1)) / frames_per_block; }
|
inline size_t num_blocks(size_t frames) { return (frames + (frames_per_block-1)) / frames_per_block; }
|
||||||
|
|
||||||
counted<kernel::init::frame_block>
|
util::counted<bootproto::frame_block>
|
||||||
build_frame_blocks(const counted<kernel::init::mem_entry> &kmap)
|
build_frame_blocks(const util::counted<bootproto::mem_entry> &kmap)
|
||||||
{
|
{
|
||||||
status_line status {L"Creating kernel frame accounting map"};
|
status_line status {L"Creating kernel frame accounting map"};
|
||||||
|
|
||||||
@@ -232,7 +235,7 @@ build_frame_blocks(const counted<kernel::init::mem_entry> &kmap)
|
|||||||
while (page_count) {
|
while (page_count) {
|
||||||
frame_block *blk = next_block++;
|
frame_block *blk = next_block++;
|
||||||
|
|
||||||
blk->flags = static_cast<kernel::init::frame_flags>(ent.attr);
|
blk->flags = static_cast<bootproto::frame_flags>(ent.attr);
|
||||||
blk->base = base_addr;
|
blk->base = base_addr;
|
||||||
base_addr += frames_per_block * page_size;
|
base_addr += frames_per_block * page_size;
|
||||||
|
|
||||||
@@ -275,9 +278,9 @@ build_frame_blocks(const counted<kernel::init::mem_entry> &kmap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fix_frame_blocks(kernel::init::args *args)
|
fix_frame_blocks(bootproto::args *args)
|
||||||
{
|
{
|
||||||
counted<frame_block> &blocks = args->frame_blocks;
|
util::counted<frame_block> &blocks = args->frame_blocks;
|
||||||
|
|
||||||
size_t size = blocks.count * sizeof(frame_block);
|
size_t size = blocks.count * sizeof(frame_block);
|
||||||
for (unsigned i = 0; i < blocks.count; ++i)
|
for (unsigned i = 0; i < blocks.count; ++i)
|
||||||
@@ -288,13 +291,13 @@ fix_frame_blocks(kernel::init::args *args)
|
|||||||
|
|
||||||
// Map the frame blocks to the appropriate address
|
// Map the frame blocks to the appropriate address
|
||||||
paging::map_pages(args, addr,
|
paging::map_pages(args, addr,
|
||||||
::memory::bitmap_start, pages, true, false);
|
bootproto::mem::bitmap_offset, pages, true, false);
|
||||||
|
|
||||||
uintptr_t offset = ::memory::bitmap_start - addr;
|
uintptr_t offset = bootproto::mem::bitmap_offset - addr;
|
||||||
|
|
||||||
for (unsigned i = 0; i < blocks.count; ++i) {
|
for (unsigned i = 0; i < blocks.count; ++i) {
|
||||||
frame_block &blk = blocks[i];
|
frame_block &blk = blocks[i];
|
||||||
blk.bitmap = offset_ptr<uint64_t>(blk.bitmap, offset);
|
blk.bitmap = util::offset_pointer(blk.bitmap, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,20 +2,19 @@
|
|||||||
/// \file memory_map.h
|
/// \file memory_map.h
|
||||||
/// Memory-map related types and functions
|
/// Memory-map related types and functions
|
||||||
|
|
||||||
#include "counted.h"
|
#include <util/counted.h>
|
||||||
#include "pointer_manipulation.h"
|
#include <util/pointers.h>
|
||||||
|
|
||||||
namespace uefi {
|
namespace uefi {
|
||||||
struct boot_services;
|
struct boot_services;
|
||||||
struct memory_descriptor;
|
struct memory_descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace kernel {
|
namespace bootproto {
|
||||||
namespace init {
|
|
||||||
struct args;
|
struct args;
|
||||||
struct frame_block;
|
struct frame_block;
|
||||||
struct mem_entry;
|
struct mem_entry;
|
||||||
}}
|
}
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
namespace memory {
|
namespace memory {
|
||||||
@@ -25,7 +24,7 @@ namespace memory {
|
|||||||
struct efi_mem_map
|
struct efi_mem_map
|
||||||
{
|
{
|
||||||
using desc = uefi::memory_descriptor;
|
using desc = uefi::memory_descriptor;
|
||||||
using iterator = offset_iterator<desc>;
|
using iterator = util::offset_iterator<desc>;
|
||||||
|
|
||||||
size_t length; ///< Total length of the map data
|
size_t length; ///< Total length of the map data
|
||||||
size_t total; ///< Total allocated space for map data
|
size_t total; ///< Total allocated space for map data
|
||||||
@@ -46,18 +45,18 @@ struct efi_mem_map
|
|||||||
inline iterator begin() { return iterator(entries, size); }
|
inline iterator begin() { return iterator(entries, size); }
|
||||||
|
|
||||||
/// Return an iterator to the end of the array
|
/// Return an iterator to the end of the array
|
||||||
inline iterator end() { return offset_ptr<desc>(entries, length); }
|
inline iterator end() { return util::offset_pointer(entries, length); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Add the kernel's memory map as a module to the kernel args.
|
/// Add the kernel's memory map as a module to the kernel args.
|
||||||
/// \returns The uefi memory map used to build the kernel map
|
/// \returns The uefi memory map used to build the kernel map
|
||||||
counted<kernel::init::mem_entry> build_kernel_map(efi_mem_map &map);
|
util::counted<bootproto::mem_entry> build_kernel_map(efi_mem_map &map);
|
||||||
|
|
||||||
/// Create the kernel frame allocation maps
|
/// Create the kernel frame allocation maps
|
||||||
counted<kernel::init::frame_block> build_frame_blocks(const counted<kernel::init::mem_entry> &kmap);
|
util::counted<bootproto::frame_block> build_frame_blocks(const util::counted<bootproto::mem_entry> &kmap);
|
||||||
|
|
||||||
/// Map the frame allocation maps to the right spot and fix up pointers
|
/// Map the frame allocation maps to the right spot and fix up pointers
|
||||||
void fix_frame_blocks(kernel::init::args *args);
|
void fix_frame_blocks(bootproto::args *args);
|
||||||
|
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
} // namespace memory
|
} // namespace memory
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#include "kernel_memory.h"
|
#include <arch/memory.h>
|
||||||
|
#include <bootproto/memory.h>
|
||||||
|
#include <util/counted.h>
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
@@ -6,7 +9,6 @@
|
|||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "paging.h"
|
#include "paging.h"
|
||||||
#include "pointer_manipulation.h"
|
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
@@ -14,8 +16,6 @@ namespace paging {
|
|||||||
|
|
||||||
using memory::alloc_type;
|
using memory::alloc_type;
|
||||||
using memory::page_size;
|
using memory::page_size;
|
||||||
using ::memory::pml4e_kernel;
|
|
||||||
using ::memory::table_entries;
|
|
||||||
|
|
||||||
// Flags: 0 0 0 1 0 0 0 0 0 0 0 1 = 0x0101
|
// Flags: 0 0 0 1 0 0 0 0 0 0 0 1 = 0x0101
|
||||||
// IGN | | | | | | | | +- Present
|
// IGN | | | | | | | | +- Present
|
||||||
@@ -58,13 +58,13 @@ constexpr uint64_t table_flags = 0x003;
|
|||||||
|
|
||||||
|
|
||||||
inline void *
|
inline void *
|
||||||
pop_pages(counted<void> &pages, size_t count)
|
pop_pages(util::counted<void> &pages, size_t count)
|
||||||
{
|
{
|
||||||
if (count > pages.count)
|
if (count > pages.count)
|
||||||
error::raise(uefi::status::out_of_resources, L"Page table cache empty", 0x7ab1e5);
|
error::raise(uefi::status::out_of_resources, L"Page table cache empty", 0x7ab1e5);
|
||||||
|
|
||||||
void *next = pages.pointer;
|
void *next = pages.pointer;
|
||||||
pages.pointer = offset_ptr<void>(pages.pointer, count*page_size);
|
pages.pointer = util::offset_pointer(pages.pointer, count*page_size);
|
||||||
pages.count -= count;
|
pages.count -= count;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
page_entry_iterator(
|
page_entry_iterator(
|
||||||
uintptr_t virt,
|
uintptr_t virt,
|
||||||
page_table *pml4,
|
page_table *pml4,
|
||||||
counted<void> &pages) :
|
util::counted<void> &pages) :
|
||||||
m_pages(pages)
|
m_pages(pages)
|
||||||
{
|
{
|
||||||
m_table[0] = pml4;
|
m_table[0] = pml4;
|
||||||
@@ -137,17 +137,17 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
counted<void> &m_pages;
|
util::counted<void> &m_pages;
|
||||||
page_table *m_table[D];
|
page_table *m_table[D];
|
||||||
uint16_t m_index[D];
|
uint16_t m_index[D];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_offset_mappings(page_table *pml4, counted<void> &pages)
|
add_offset_mappings(page_table *pml4, util::counted<void> &pages)
|
||||||
{
|
{
|
||||||
uintptr_t phys = 0;
|
uintptr_t phys = 0;
|
||||||
uintptr_t virt = ::memory::page_offset; // Start of offset-mapped area
|
uintptr_t virt = bootproto::mem::linear_offset; // Start of offset-mapped area
|
||||||
size_t page_count = 64 * 1024; // 64 TiB of 1 GiB pages
|
size_t page_count = 64 * 1024; // 64 TiB of 1 GiB pages
|
||||||
constexpr size_t GiB = 0x40000000ull;
|
constexpr size_t GiB = 0x40000000ull;
|
||||||
|
|
||||||
@@ -164,9 +164,12 @@ add_offset_mappings(page_table *pml4, counted<void> &pages)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_kernel_pds(page_table *pml4, counted<void> &pages)
|
add_kernel_pds(page_table *pml4, util::counted<void> &pages)
|
||||||
{
|
{
|
||||||
for (unsigned i = pml4e_kernel; i < table_entries; ++i)
|
constexpr unsigned start = arch::kernel_root_index;
|
||||||
|
constexpr unsigned end = arch::table_entries;
|
||||||
|
|
||||||
|
for (unsigned i = start; i < end; ++i)
|
||||||
pml4->set(i, pop_pages(pages, 1), table_flags);
|
pml4->set(i, pop_pages(pages, 1), table_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +181,8 @@ add_current_mappings(page_table *new_pml4)
|
|||||||
asm volatile ( "mov %%cr3, %0" : "=r" (old_pml4) );
|
asm volatile ( "mov %%cr3, %0" : "=r" (old_pml4) );
|
||||||
|
|
||||||
// Only copy mappings in the lower half
|
// Only copy mappings in the lower half
|
||||||
for (int i = 0; i < ::memory::pml4e_kernel; ++i) {
|
constexpr unsigned halfway = arch::kernel_root_index;
|
||||||
|
for (int i = 0; i < halfway; ++i) {
|
||||||
uint64_t entry = old_pml4->entries[i];
|
uint64_t entry = old_pml4->entries[i];
|
||||||
if (entry & 1)
|
if (entry & 1)
|
||||||
new_pml4->entries[i] = entry;
|
new_pml4->entries[i] = entry;
|
||||||
@@ -186,7 +190,7 @@ add_current_mappings(page_table *new_pml4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
allocate_tables(kernel::init::args *args)
|
allocate_tables(bootproto::args *args)
|
||||||
{
|
{
|
||||||
status_line status(L"Allocating initial page tables");
|
status_line status(L"Allocating initial page tables");
|
||||||
|
|
||||||
@@ -221,7 +225,7 @@ constexpr bool has_flag(E set, E flag) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
map_pages(
|
map_pages(
|
||||||
kernel::init::args *args,
|
bootproto::args *args,
|
||||||
uintptr_t phys, uintptr_t virt,
|
uintptr_t phys, uintptr_t virt,
|
||||||
size_t count, bool write_flag, bool exe_flag)
|
size_t count, bool write_flag, bool exe_flag)
|
||||||
{
|
{
|
||||||
@@ -251,10 +255,10 @@ map_pages(
|
|||||||
|
|
||||||
void
|
void
|
||||||
map_section(
|
map_section(
|
||||||
kernel::init::args *args,
|
bootproto::args *args,
|
||||||
const kernel::init::program_section §ion)
|
const bootproto::program_section §ion)
|
||||||
{
|
{
|
||||||
using kernel::init::section_flags;
|
using bootproto::section_flags;
|
||||||
|
|
||||||
map_pages(
|
map_pages(
|
||||||
args,
|
args,
|
||||||
@@ -267,8 +271,8 @@ map_section(
|
|||||||
|
|
||||||
void
|
void
|
||||||
map_program(
|
map_program(
|
||||||
kernel::init::args *args,
|
bootproto::args *args,
|
||||||
kernel::init::program &program)
|
bootproto::program &program)
|
||||||
{
|
{
|
||||||
for (auto §ion : program.sections)
|
for (auto §ion : program.sections)
|
||||||
paging::map_section(args, section);
|
paging::map_section(args, section);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// Page table structure and related definitions
|
/// Page table structure and related definitions
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <uefi/boot_services.h>
|
#include <uefi/boot_services.h>
|
||||||
#include "kernel_args.h"
|
#include <bootproto/kernel.h>
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
namespace paging {
|
namespace paging {
|
||||||
@@ -30,7 +30,7 @@ struct page_table
|
|||||||
/// and kernel args' `page_table_cache` and `num_free_tables` are updated with
|
/// and kernel args' `page_table_cache` and `num_free_tables` are updated with
|
||||||
/// the leftover space.
|
/// the leftover space.
|
||||||
/// \arg args The kernel args struct, used for the page table cache and pml4
|
/// \arg args The kernel args struct, used for the page table cache and pml4
|
||||||
void allocate_tables(kernel::init::args *args);
|
void allocate_tables(bootproto::args *args);
|
||||||
|
|
||||||
/// Copy existing page table entries to a new page table. Does not do a deep
|
/// Copy existing page table entries to a new page table. Does not do a deep
|
||||||
/// copy - the new PML4 is updated to point to the existing next-level page
|
/// copy - the new PML4 is updated to point to the existing next-level page
|
||||||
@@ -46,7 +46,7 @@ void add_current_mappings(page_table *new_pml4);
|
|||||||
/// \arg write_flag If true, mark the pages writeable
|
/// \arg write_flag If true, mark the pages writeable
|
||||||
/// \arg exe_flag If true, mark the pages executable
|
/// \arg exe_flag If true, mark the pages executable
|
||||||
void map_pages(
|
void map_pages(
|
||||||
kernel::init::args *args,
|
bootproto::args *args,
|
||||||
uintptr_t phys, uintptr_t virt,
|
uintptr_t phys, uintptr_t virt,
|
||||||
size_t count, bool write_flag, bool exe_flag);
|
size_t count, bool write_flag, bool exe_flag);
|
||||||
|
|
||||||
@@ -55,8 +55,8 @@ void map_pages(
|
|||||||
/// \arg args The kernel args struct, used for the page table cache and pml4
|
/// \arg args The kernel args struct, used for the page table cache and pml4
|
||||||
/// \arg program The program to load
|
/// \arg program The program to load
|
||||||
void map_program(
|
void map_program(
|
||||||
kernel::init::args *args,
|
bootproto::args *args,
|
||||||
kernel::init::program &program);
|
bootproto::program &program);
|
||||||
|
|
||||||
} // namespace paging
|
} // namespace paging
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "init_args.h"
|
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,16 @@
|
|||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "init_args.h"
|
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
|
|
||||||
namespace boot {
|
namespace boot {
|
||||||
namespace video {
|
namespace video {
|
||||||
|
|
||||||
using kernel::init::fb_layout;
|
using bootproto::fb_layout;
|
||||||
using kernel::init::fb_type;
|
using bootproto::fb_type;
|
||||||
using kernel::init::module_flags;
|
using bootproto::module_flags;
|
||||||
using kernel::init::module_framebuffer;
|
using bootproto::module_framebuffer;
|
||||||
using kernel::init::module_type;
|
using bootproto::module_type;
|
||||||
|
|
||||||
static uefi::protos::graphics_output *
|
static uefi::protos::graphics_output *
|
||||||
get_gop(uefi::boot_services *bs)
|
get_gop(uefi::boot_services *bs)
|
||||||
@@ -109,7 +108,7 @@ pick_mode(uefi::boot_services *bs)
|
|||||||
void
|
void
|
||||||
make_module(screen *s)
|
make_module(screen *s)
|
||||||
{
|
{
|
||||||
using kernel::init::module_framebuffer;
|
using bootproto::module_framebuffer;
|
||||||
module_framebuffer *modfb = g_alloc.allocate_module<module_framebuffer>();
|
module_framebuffer *modfb = g_alloc.allocate_module<module_framebuffer>();
|
||||||
modfb->mod_type = module_type::framebuffer;
|
modfb->mod_type = module_type::framebuffer;
|
||||||
modfb->type = fb_type::uefi;
|
modfb->type = fb_type::uefi;
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "init_args.h"
|
#include <bootproto/init.h>
|
||||||
|
#include <util/counted.h>
|
||||||
|
|
||||||
namespace uefi {
|
namespace uefi {
|
||||||
struct boot_services;
|
struct boot_services;
|
||||||
@@ -14,11 +15,11 @@ namespace uefi {
|
|||||||
namespace boot {
|
namespace boot {
|
||||||
namespace video {
|
namespace video {
|
||||||
|
|
||||||
using kernel::init::video_mode;
|
using bootproto::video_mode;
|
||||||
using layout = kernel::init::fb_layout;
|
using layout = bootproto::fb_layout;
|
||||||
|
|
||||||
struct screen {
|
struct screen {
|
||||||
buffer framebuffer;
|
util::buffer framebuffer;
|
||||||
video_mode mode;
|
video_mode mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
31
src/include/arch/amd64/memory.h
Normal file
31
src/include/arch/amd64/memory.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
/// \file arch/amd64/memory.h
|
||||||
|
/// Architecture-specific constants related to memory and paging
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace arch {
|
||||||
|
|
||||||
|
/// Size of a single page frame.
|
||||||
|
constexpr size_t frame_size = 0x1000;
|
||||||
|
|
||||||
|
/// Number of bits of addressing within a page
|
||||||
|
constexpr size_t frame_bits = 12;
|
||||||
|
|
||||||
|
/// Number of bits mapped per page table level
|
||||||
|
constexpr size_t table_bits = 9;
|
||||||
|
|
||||||
|
/// Number of page_table entries
|
||||||
|
constexpr unsigned table_entries = 512;
|
||||||
|
|
||||||
|
/// First index in the root page table for kernel space
|
||||||
|
constexpr unsigned kernel_root_index = table_entries / 2;
|
||||||
|
|
||||||
|
/// Number of page table levels
|
||||||
|
/// TODO: Add five-level paging support
|
||||||
|
constexpr unsigned page_table_levels = 4;
|
||||||
|
|
||||||
|
/// Start of kernel memory.
|
||||||
|
constexpr uintptr_t kernel_offset = 0ull - (1ull << (page_table_levels * table_bits + frame_bits - 1));
|
||||||
|
|
||||||
|
} // namespace arch
|
||||||
9
src/include/arch/memory.h
Normal file
9
src/include/arch/memory.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
/// \file arch/memory.h
|
||||||
|
/// Include architecture-specific constants related to memory and paging
|
||||||
|
|
||||||
|
#if defined(__amd64__) || defined(__x86_64__)
|
||||||
|
#include <arch/amd64/memory.h>
|
||||||
|
#else
|
||||||
|
#error Unsupported platform.
|
||||||
|
#endif
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
/// \file kernel_memory.h
|
|
||||||
/// Constants related to the kernel's memory layout
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace memory {
|
|
||||||
|
|
||||||
/// Size of a single page frame.
|
|
||||||
constexpr size_t frame_size = 0x1000;
|
|
||||||
|
|
||||||
/// Number of bits of addressing within a page
|
|
||||||
constexpr size_t frame_bits = 12;
|
|
||||||
|
|
||||||
/// Start of kernel memory.
|
|
||||||
constexpr uintptr_t kernel_offset = 0xffff800000000000ull;
|
|
||||||
|
|
||||||
/// Offset from physical where page tables are mapped.
|
|
||||||
constexpr uintptr_t page_offset = 0xffffc00000000000ull;
|
|
||||||
|
|
||||||
/// Max number of pages for a kernel stack
|
|
||||||
constexpr unsigned kernel_stack_pages = 2;
|
|
||||||
|
|
||||||
/// Max number of pages for a kernel buffer
|
|
||||||
constexpr unsigned kernel_buffer_pages = 16;
|
|
||||||
|
|
||||||
/// Max size of the kernel heap
|
|
||||||
constexpr size_t kernel_max_heap = 0x8000000000ull; // 512GiB
|
|
||||||
|
|
||||||
/// Start of the kernel heap
|
|
||||||
constexpr uintptr_t heap_start = page_offset - kernel_max_heap;
|
|
||||||
|
|
||||||
/// Max size of the kernel stacks area
|
|
||||||
constexpr size_t kernel_max_stacks = 0x8000000000ull; // 512GiB
|
|
||||||
|
|
||||||
/// Start of the kernel stacks
|
|
||||||
constexpr uintptr_t stacks_start = heap_start - kernel_max_stacks;
|
|
||||||
|
|
||||||
/// Max size of kernel buffers area
|
|
||||||
constexpr size_t kernel_max_buffers = 0x8000000000ull; // 512GiB
|
|
||||||
|
|
||||||
/// Start of kernel buffers
|
|
||||||
constexpr uintptr_t buffers_start = stacks_start - kernel_max_buffers;
|
|
||||||
|
|
||||||
/// Max size of kernel bitmap area
|
|
||||||
constexpr size_t kernel_max_bitmap = 0x8000000000ull; // 512GiB
|
|
||||||
|
|
||||||
/// Start of kernel bitmap
|
|
||||||
constexpr uintptr_t bitmap_start = buffers_start - kernel_max_bitmap;
|
|
||||||
|
|
||||||
/// First kernel space PML4 entry
|
|
||||||
constexpr unsigned pml4e_kernel = 256;
|
|
||||||
|
|
||||||
/// First offset-mapped space PML4 entry
|
|
||||||
constexpr unsigned pml4e_offset = 384;
|
|
||||||
|
|
||||||
/// Number of page_table entries
|
|
||||||
constexpr unsigned table_entries = 512;
|
|
||||||
|
|
||||||
/// Helper to determine if a physical address can be accessed
|
|
||||||
/// through the page_offset area.
|
|
||||||
inline bool page_mappable(uintptr_t a) { return (a & page_offset) == 0; }
|
|
||||||
|
|
||||||
/// Convert a physical address to a virtual one (in the offset-mapped area)
|
|
||||||
template <typename T> T * to_virtual(uintptr_t a) {
|
|
||||||
return reinterpret_cast<T*>(a|page_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a physical address to a virtual one (in the offset-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
|
|
||||||
inline size_t page_count(size_t bytes) {
|
|
||||||
return ((bytes - 1) >> 12) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the given address, aligned to the next lowest page
|
|
||||||
inline uintptr_t page_align_down(uintptr_t a) { return a & ~(frame_size-1); }
|
|
||||||
|
|
||||||
/// Get the given address, aligned to the next page
|
|
||||||
inline uintptr_t page_align_up(uintptr_t a) { return page_align_down(a-1) + frame_size; }
|
|
||||||
|
|
||||||
} // namespace memory
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <util/misc.h>
|
#include <util/misc.h> // for byteswap32
|
||||||
#include <enum_bitfields.h>
|
#include <enum_bitfields.h>
|
||||||
|
|
||||||
struct acpi_table_header
|
struct acpi_table_header
|
||||||
@@ -22,7 +22,7 @@ struct acpi_table_header
|
|||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define TABLE_HEADER(signature) \
|
#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;
|
acpi_table_header header;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
uint64_t lapic::s_ticks_per_us = 0;
|
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) :
|
apic::apic(uintptr_t base) :
|
||||||
m_base(memory::to_virtual<uint32_t>(base))
|
m_base(mem::to_virtual<uint32_t>(base))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "msr.h"
|
#include "msr.h"
|
||||||
#include "objects/vm_area.h"
|
#include "objects/vm_area.h"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <util/misc.h> // for checksum
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "acpi_tables.h"
|
#include "acpi_tables.h"
|
||||||
@@ -8,7 +10,6 @@
|
|||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "objects/endpoint.h"
|
#include "objects/endpoint.h"
|
||||||
@@ -47,7 +48,7 @@ struct acpi2_rsdp
|
|||||||
bool
|
bool
|
||||||
acpi_table_header::validate(uint32_t expected_type) const
|
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);
|
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.");
|
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));
|
reinterpret_cast<const acpi1_rsdp *>(root_table));
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(acpi1->signature); ++i)
|
for (int i = 0; i < sizeof(acpi1->signature); ++i)
|
||||||
kassert(acpi1->signature[i] == expected_signature[i],
|
kassert(acpi1->signature[i] == expected_signature[i],
|
||||||
"ACPI RSDP table signature mismatch");
|
"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(sum == 0, "ACPI 1.0 RSDP checksum mismatch.");
|
||||||
|
|
||||||
kassert(acpi1->revision > 1, "ACPI 1.0 not supported.");
|
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 =
|
const acpi2_rsdp *acpi2 =
|
||||||
reinterpret_cast<const acpi2_rsdp *>(acpi1);
|
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.");
|
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 *
|
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*));
|
size_t num_tables = acpi_table_entries(xsdt, sizeof(void*));
|
||||||
for (size_t i = 0; i < num_tables; ++i) {
|
for (size_t i = 0; i < num_tables; ++i) {
|
||||||
const acpi_table_header *header =
|
const acpi_table_header *header =
|
||||||
memory::to_virtual(xsdt->headers[i]);
|
mem::to_virtual(xsdt->headers[i]);
|
||||||
|
|
||||||
put_sig(sig, header->type);
|
put_sig(sig, header->type);
|
||||||
log::debug(logs::device, " Found table %s", sig);
|
log::debug(logs::device, " Found table %s", sig);
|
||||||
@@ -212,8 +213,8 @@ device_manager::load_apic(const acpi_table_header *header)
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0: { // Local APIC
|
case 0: { // Local APIC
|
||||||
uint8_t uid = read_from<uint8_t>(p+2);
|
uint8_t uid = util::read_from<uint8_t>(p+2);
|
||||||
uint8_t id = read_from<uint8_t>(p+3);
|
uint8_t id = util::read_from<uint8_t>(p+3);
|
||||||
m_apic_ids.append(id);
|
m_apic_ids.append(id);
|
||||||
|
|
||||||
log::debug(logs::device, " Local APIC uid %x id %x", uid, 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;
|
break;
|
||||||
|
|
||||||
case 1: { // I/O APIC
|
case 1: { // I/O APIC
|
||||||
uintptr_t base = read_from<uint32_t>(p+4);
|
uintptr_t base = util::read_from<uint32_t>(p+4);
|
||||||
uint32_t base_gsi = read_from<uint32_t>(p+8);
|
uint32_t base_gsi = util::read_from<uint32_t>(p+8);
|
||||||
m_ioapics.emplace(base, base_gsi);
|
m_ioapics.emplace(base, base_gsi);
|
||||||
|
|
||||||
log::debug(logs::device, " IO APIC gsi %x base %x", base_gsi, base);
|
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
|
case 2: { // Interrupt source override
|
||||||
irq_override o;
|
irq_override o;
|
||||||
o.source = read_from<uint8_t>(p+3);
|
o.source = util::read_from<uint8_t>(p+3);
|
||||||
o.gsi = read_from<uint32_t>(p+4);
|
o.gsi = util::read_from<uint32_t>(p+4);
|
||||||
o.flags = read_from<uint16_t>(p+8);
|
o.flags = util::read_from<uint16_t>(p+8);
|
||||||
m_overrides.append(o);
|
m_overrides.append(o);
|
||||||
|
|
||||||
log::debug(logs::device, " Intr source override IRQ %d -> %d Pol %d Tri %d",
|
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
|
case 4: {// LAPIC NMI
|
||||||
apic_nmi nmi;
|
apic_nmi nmi;
|
||||||
nmi.cpu = read_from<uint8_t>(p + 2);
|
nmi.cpu = util::read_from<uint8_t>(p + 2);
|
||||||
nmi.lint = read_from<uint8_t>(p + 5);
|
nmi.lint = util::read_from<uint8_t>(p + 5);
|
||||||
nmi.flags = read_from<uint16_t>(p + 3);
|
nmi.flags = util::read_from<uint16_t>(p + 3);
|
||||||
m_nmis.append(nmi);
|
m_nmis.append(nmi);
|
||||||
|
|
||||||
log::debug(logs::device, " LAPIC NMI Proc %02x LINT%d Pol %d Tri %d",
|
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].group = mcfge.group;
|
||||||
m_pci[i].bus_start = mcfge.bus_start;
|
m_pci[i].bus_start = mcfge.bus_start;
|
||||||
m_pci[i].bus_end = mcfge.bus_end;
|
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",
|
log::debug(logs::device, " Found MCFG entry: base %lx group %d bus %d-%d",
|
||||||
mcfge.base, mcfge.group, mcfge.bus_start, mcfge.bus_end);
|
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);
|
log::debug(logs::device, " pci vendor id: %04x", pci_vendor_id);
|
||||||
|
|
||||||
m_hpets.emplace(hpet->index,
|
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
|
void
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
#include <bootproto/kernel.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "frame_allocator.h"
|
#include "frame_allocator.h"
|
||||||
#include "kernel_args.h"
|
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
using memory::frame_size;
|
using mem::frame_size;
|
||||||
|
|
||||||
|
|
||||||
frame_allocator &
|
frame_allocator &
|
||||||
@@ -14,7 +15,7 @@ frame_allocator::get()
|
|||||||
return g_frame_allocator;
|
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_blocks {frames},
|
||||||
m_count {count}
|
m_count {count}
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,16 +5,15 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <util/spinlock.h>
|
#include <util/spinlock.h>
|
||||||
|
|
||||||
namespace kernel {
|
namespace bootproto {
|
||||||
namespace init {
|
|
||||||
struct frame_block;
|
struct frame_block;
|
||||||
}}
|
}
|
||||||
|
|
||||||
/// Allocator for physical memory frames
|
/// Allocator for physical memory frames
|
||||||
class frame_allocator
|
class frame_allocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using frame_block = kernel::init::frame_block;
|
using frame_block = bootproto::frame_block;
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// \arg blocks The bootloader-supplied frame bitmap block list
|
/// \arg blocks The bootloader-supplied frame bitmap block list
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <util/pointers.h>
|
||||||
#include <util/util.h>
|
#include <util/util.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
@@ -44,8 +45,8 @@ struct heap_allocator::mem_header
|
|||||||
set_next(nullptr);
|
set_next(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline mem_header * next() { return mask_pointer(m_next, 0x3f); }
|
inline mem_header * next() { return util::mask_pointer(m_next, 0x3f); }
|
||||||
inline mem_header * prev() { return mask_pointer(m_prev, 0x3f); }
|
inline mem_header * prev() { return util::mask_pointer(m_prev, 0x3f); }
|
||||||
|
|
||||||
inline mem_header * buddy() const {
|
inline mem_header * buddy() const {
|
||||||
return reinterpret_cast<mem_header *>(
|
return reinterpret_cast<mem_header *>(
|
||||||
@@ -155,7 +156,7 @@ heap_allocator::ensure_block(unsigned order)
|
|||||||
} else {
|
} else {
|
||||||
mem_header *orig = pop_free(order + 1);
|
mem_header *orig = pop_free(order + 1);
|
||||||
if (orig) {
|
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);
|
new (next) mem_header(orig, nullptr, order);
|
||||||
|
|
||||||
orig->set_next(next);
|
orig->set_next(next);
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#include "kernel_memory.h"
|
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "hpet.h"
|
#include "hpet.h"
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "printf/printf.h"
|
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
@@ -9,14 +7,16 @@
|
|||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "objects/process.h"
|
#include "objects/process.h"
|
||||||
|
#include "printf/printf.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "vm_space.h"
|
#include "vm_space.h"
|
||||||
|
|
||||||
static const uint16_t PIC1 = 0x20;
|
static const uint16_t PIC1 = 0x20;
|
||||||
static const uint16_t PIC2 = 0xa0;
|
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" {
|
extern "C" {
|
||||||
void isr_handler(cpu_state*);
|
void isr_handler(cpu_state*);
|
||||||
@@ -119,7 +119,7 @@ isr_handler(cpu_state *regs)
|
|||||||
uintptr_t cr2 = 0;
|
uintptr_t cr2 = 0;
|
||||||
__asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2));
|
__asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2));
|
||||||
|
|
||||||
bool user = cr2 < memory::kernel_offset;
|
bool user = cr2 < mem::kernel_offset;
|
||||||
vm_space::fault_type ft =
|
vm_space::fault_type ft =
|
||||||
static_cast<vm_space::fault_type>(regs->errorcode);
|
static_cast<vm_space::fault_type>(regs->errorcode);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ kernel = module("kernel",
|
|||||||
default = True,
|
default = True,
|
||||||
output = "jsix.elf",
|
output = "jsix.elf",
|
||||||
targets = [ "kernel" ],
|
targets = [ "kernel" ],
|
||||||
deps = [ "util", "cpu" ],
|
deps = [ "util", "cpu", "bootproto" ],
|
||||||
includes = [ "." ],
|
includes = [ "." ],
|
||||||
sources = [
|
sources = [
|
||||||
"apic.cpp",
|
"apic.cpp",
|
||||||
@@ -15,6 +15,7 @@ kernel = module("kernel",
|
|||||||
"clock.cpp",
|
"clock.cpp",
|
||||||
"console.cpp",
|
"console.cpp",
|
||||||
"cpprt.cpp",
|
"cpprt.cpp",
|
||||||
|
"cpu.cpp",
|
||||||
"debug.cpp",
|
"debug.cpp",
|
||||||
"debug.s",
|
"debug.s",
|
||||||
"device_manager.cpp",
|
"device_manager.cpp",
|
||||||
@@ -29,6 +30,7 @@ kernel = module("kernel",
|
|||||||
"io.cpp",
|
"io.cpp",
|
||||||
"log.cpp",
|
"log.cpp",
|
||||||
"logger.cpp",
|
"logger.cpp",
|
||||||
|
"main.cpp",
|
||||||
"memory.cpp",
|
"memory.cpp",
|
||||||
"memory_bootstrap.cpp",
|
"memory_bootstrap.cpp",
|
||||||
"msr.cpp",
|
"msr.cpp",
|
||||||
@@ -45,6 +47,7 @@ kernel = module("kernel",
|
|||||||
"printf/printf.c",
|
"printf/printf.c",
|
||||||
"scheduler.cpp",
|
"scheduler.cpp",
|
||||||
"serial.cpp",
|
"serial.cpp",
|
||||||
|
"syscall.s",
|
||||||
"syscalls/channel.cpp",
|
"syscalls/channel.cpp",
|
||||||
"syscalls/endpoint.cpp",
|
"syscalls/endpoint.cpp",
|
||||||
"syscalls/object.cpp",
|
"syscalls/object.cpp",
|
||||||
@@ -58,14 +61,41 @@ kernel = module("kernel",
|
|||||||
])
|
])
|
||||||
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
definitions = glob('definitions/**/*.def', recursive=True)
|
from os.path import join
|
||||||
sysinc = kernel.add_input("syscalls.inc.cog", deps=definitions)
|
|
||||||
kernel.add_input("syscall.s", deps=[sysinc])
|
|
||||||
|
|
||||||
|
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)
|
sysh = kernel.add_input("syscall.h.cog", deps=definitions)
|
||||||
sysc = kernel.add_input("syscall.cpp.cog", deps=definitions + [sysh])
|
sysc = kernel.add_input("syscall.cpp.cog", deps=definitions + [sysh])
|
||||||
|
|
||||||
kernel.add_input("main.cpp", deps=[sysh])
|
kernel.add_depends(["syscall.s"], [sysinc])
|
||||||
kernel.add_input("cpu.cpp", deps=[sysh])
|
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"]
|
kernel.variables['ldflags'] = ["${ldflags}", "-T", "${source_root}/src/kernel/kernel.ld"]
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <bootproto/kernel.h>
|
||||||
#include <j6/signals.h>
|
#include <j6/signals.h>
|
||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
#include <kernel_args.h>
|
|
||||||
#include <kernel_memory.h>
|
|
||||||
|
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
@@ -19,6 +18,7 @@
|
|||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "msr.h"
|
#include "msr.h"
|
||||||
#include "objects/channel.h"
|
#include "objects/channel.h"
|
||||||
#include "objects/event.h"
|
#include "objects/event.h"
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void kernel_main(kernel::init::args *args);
|
void kernel_main(bootproto::args *args);
|
||||||
void (*__ctors)(void);
|
void (*__ctors)(void);
|
||||||
void (*__ctors_end)(void);
|
void (*__ctors_end)(void);
|
||||||
void long_ap_startup(cpu_data *cpu);
|
void long_ap_startup(cpu_data *cpu);
|
||||||
@@ -45,15 +45,13 @@ extern "C" {
|
|||||||
void init_ap_trampoline(void*, cpu_data *, void (*)());
|
void init_ap_trampoline(void*, cpu_data *, void (*)());
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace kernel;
|
|
||||||
|
|
||||||
volatile size_t ap_startup_count;
|
volatile size_t ap_startup_count;
|
||||||
static bool scheduler_ready = false;
|
static bool scheduler_ready = false;
|
||||||
|
|
||||||
/// Bootstrap the memory managers.
|
/// Bootstrap the memory managers.
|
||||||
void memory_initialize_pre_ctors(init::args &kargs);
|
void memory_initialize_pre_ctors(bootproto::args &kargs);
|
||||||
void memory_initialize_post_ctors(init::args &kargs);
|
void memory_initialize_post_ctors(bootproto::args &kargs);
|
||||||
void load_init_server(init::program &program, uintptr_t modules_address);
|
void load_init_server(bootproto::program &program, uintptr_t modules_address);
|
||||||
|
|
||||||
unsigned start_aps(lapic &apic, const util::vector<uint8_t> &ids, void *kpml4);
|
unsigned start_aps(lapic &apic, const util::vector<uint8_t> &ids, void *kpml4);
|
||||||
|
|
||||||
@@ -80,11 +78,11 @@ run_constructors()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
kernel_main(init::args *args)
|
kernel_main(bootproto::args *args)
|
||||||
{
|
{
|
||||||
if (args->panic) {
|
if (args->panic) {
|
||||||
IDT::set_nmi_handler(args->panic->entrypoint);
|
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();
|
init_console();
|
||||||
@@ -108,7 +106,7 @@ kernel_main(init::args *args)
|
|||||||
cpu->rsp0 = idle_stack_end;
|
cpu->rsp0 = idle_stack_end;
|
||||||
cpu_early_init(cpu);
|
cpu_early_init(cpu);
|
||||||
|
|
||||||
kassert(args->magic == init::args_magic,
|
kassert(args->magic == bootproto::args_magic,
|
||||||
"Bad kernel args magic number");
|
"Bad kernel args magic number");
|
||||||
|
|
||||||
log::debug(logs::boot, "jsix init args are at: %016lx", args);
|
log::debug(logs::boot, "jsix init args are at: %016lx", args);
|
||||||
@@ -193,8 +191,8 @@ kernel_main(init::args *args)
|
|||||||
unsigned
|
unsigned
|
||||||
start_aps(lapic &apic, const util::vector<uint8_t> &ids, void *kpml4)
|
start_aps(lapic &apic, const util::vector<uint8_t> &ids, void *kpml4)
|
||||||
{
|
{
|
||||||
using memory::frame_size;
|
using mem::frame_size;
|
||||||
using memory::kernel_stack_pages;
|
using mem::kernel_stack_pages;
|
||||||
|
|
||||||
extern size_t ap_startup_code_size;
|
extern size_t ap_startup_code_size;
|
||||||
extern process &g_kernel_process;
|
extern process &g_kernel_process;
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
79
src/kernel/memory.h.cog
Normal 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
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <arch/memory.h>
|
||||||
|
#include <bootproto/kernel.h>
|
||||||
#include <j6/init.h>
|
#include <j6/init.h>
|
||||||
#include <util/no_construct.h>
|
#include <util/no_construct.h>
|
||||||
#include <kernel_args.h>
|
|
||||||
#include <enum_bitfields.h>
|
#include <enum_bitfields.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
#include "heap_allocator.h"
|
#include "heap_allocator.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "msr.h"
|
#include "msr.h"
|
||||||
#include "objects/process.h"
|
#include "objects/process.h"
|
||||||
#include "objects/thread.h"
|
#include "objects/thread.h"
|
||||||
@@ -19,18 +21,12 @@
|
|||||||
#include "objects/vm_area.h"
|
#include "objects/vm_area.h"
|
||||||
#include "vm_space.h"
|
#include "vm_space.h"
|
||||||
|
|
||||||
using memory::heap_start;
|
namespace bootproto {
|
||||||
using memory::kernel_max_heap;
|
is_bitfield(section_flags);
|
||||||
|
}
|
||||||
|
|
||||||
namespace kernel {
|
using bootproto::allocation_register;
|
||||||
namespace init {
|
using bootproto::section_flags;
|
||||||
is_bitfield(section_flags);
|
|
||||||
}}
|
|
||||||
|
|
||||||
using kernel::init::allocation_register;
|
|
||||||
using kernel::init::section_flags;
|
|
||||||
|
|
||||||
using namespace kernel;
|
|
||||||
|
|
||||||
extern "C" void initialize_main_thread();
|
extern "C" void initialize_main_thread();
|
||||||
extern "C" uintptr_t initialize_main_user_stack();
|
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_stacks = __g_kernel_stacks_storage.value;
|
||||||
|
|
||||||
vm_area_guarded g_kernel_buffers {
|
vm_area_guarded g_kernel_buffers {
|
||||||
memory::buffers_start,
|
mem::buffers_offset,
|
||||||
memory::kernel_buffer_pages,
|
mem::kernel_buffer_pages,
|
||||||
memory::kernel_max_buffers,
|
mem::buffers_size,
|
||||||
vm_flags::write};
|
vm_flags::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); }
|
||||||
@@ -67,26 +63,26 @@ void kfree(void *p) { return g_kernel_heap.free(p); }
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
uintptr_t
|
uintptr_t
|
||||||
get_physical_page(T *p) {
|
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
|
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);
|
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};
|
new (&g_frame_allocator) frame_allocator {blocks, kargs.frame_blocks.count};
|
||||||
|
|
||||||
// Mark all the things the bootloader allocated for us as used
|
// Mark all the things the bootloader allocated for us as used
|
||||||
allocation_register *reg = kargs.allocations;
|
allocation_register *reg = kargs.allocations;
|
||||||
while (reg) {
|
while (reg) {
|
||||||
for (auto &alloc : reg->entries)
|
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);
|
g_frame_allocator.used(alloc.address, alloc.count);
|
||||||
reg = reg->next;
|
reg = reg->next;
|
||||||
}
|
}
|
||||||
@@ -95,27 +91,27 @@ memory_initialize_pre_ctors(init::args &kargs)
|
|||||||
vm_space &vm = kp->space();
|
vm_space &vm = kp->space();
|
||||||
|
|
||||||
vm_area *heap = new (&g_kernel_heap_area)
|
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 {
|
vm_area *stacks = new (&g_kernel_stacks) vm_area_guarded {
|
||||||
memory::stacks_start,
|
mem::stacks_offset,
|
||||||
memory::kernel_stack_pages,
|
mem::kernel_stack_pages,
|
||||||
memory::kernel_max_stacks,
|
mem::stacks_size,
|
||||||
vm_flags::write};
|
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
|
// 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;
|
kpml4->entries[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
memory_initialize_post_ctors(init::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(memory::buffers_start, &g_kernel_buffers);
|
vm.add(mem::buffers_offset, &g_kernel_buffers);
|
||||||
|
|
||||||
g_frame_allocator.free(
|
g_frame_allocator.free(
|
||||||
get_physical_page(kargs.page_tables.pointer),
|
get_physical_page(kargs.page_tables.pointer),
|
||||||
@@ -179,7 +175,7 @@ log_mtrrs()
|
|||||||
|
|
||||||
|
|
||||||
void
|
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;
|
process *p = new process;
|
||||||
p->add_handle(&system::get());
|
p->add_handle(&system::get());
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "kernel_memory.h"
|
#include "memory.h"
|
||||||
#include "objects/channel.h"
|
#include "objects/channel.h"
|
||||||
#include "objects/vm_area.h"
|
#include "objects/vm_area.h"
|
||||||
|
|
||||||
extern vm_area_guarded g_kernel_buffers;
|
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() :
|
channel::channel() :
|
||||||
m_len(0),
|
m_len(0),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <j6/signals.h>
|
#include <j6/signals.h>
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@@ -42,7 +43,7 @@ thread::from_tcb(TCB *tcb)
|
|||||||
{
|
{
|
||||||
static ptrdiff_t offset =
|
static ptrdiff_t offset =
|
||||||
-1 * static_cast<ptrdiff_t>(offsetof(thread, m_tcb));
|
-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; }
|
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
|
void
|
||||||
thread::setup_kernel_stack()
|
thread::setup_kernel_stack()
|
||||||
{
|
{
|
||||||
using memory::frame_size;
|
using mem::frame_size;
|
||||||
using memory::kernel_stack_pages;
|
using mem::kernel_stack_pages;
|
||||||
static constexpr size_t stack_bytes = kernel_stack_pages * frame_size;
|
static constexpr size_t stack_bytes = kernel_stack_pages * frame_size;
|
||||||
|
|
||||||
constexpr unsigned null_frame_entries = 2;
|
constexpr unsigned null_frame_entries = 2;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#include "kernel_memory.h"
|
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "frame_allocator.h"
|
#include "frame_allocator.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "objects/vm_area.h"
|
#include "objects/vm_area.h"
|
||||||
#include "page_tree.h"
|
#include "page_tree.h"
|
||||||
#include "vm_space.h"
|
#include "vm_space.h"
|
||||||
|
|
||||||
using memory::frame_size;
|
using mem::frame_size;
|
||||||
|
|
||||||
vm_area::vm_area(size_t size, vm_flags flags) :
|
vm_area::vm_area(size_t size, vm_flags flags) :
|
||||||
m_size {size},
|
m_size {size},
|
||||||
@@ -74,7 +74,7 @@ vm_area_fixed::~vm_area_fixed()
|
|||||||
if (m_flags && vm_flags::mmio)
|
if (m_flags && vm_flags::mmio)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size_t pages = memory::page_count(m_size);
|
size_t pages = mem::page_count(m_size);
|
||||||
frame_allocator::get().free(m_start, pages);
|
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) :
|
vm_area_guarded::vm_area_guarded(uintptr_t start, size_t buf_pages, size_t size, vm_flags flags) :
|
||||||
m_start {start},
|
m_start {start},
|
||||||
m_pages {buf_pages},
|
m_pages {buf_pages},
|
||||||
m_next {memory::frame_size},
|
m_next {mem::frame_size},
|
||||||
vm_area_open {size, flags}
|
vm_area_open {size, flags}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ vm_area_guarded::get_section()
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t addr = m_next;
|
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;
|
return m_start + addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
#include <enum_bitfields.h>
|
#include <enum_bitfields.h>
|
||||||
|
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "objects/kobject.h"
|
#include "objects/kobject.h"
|
||||||
|
|
||||||
class page_tree;
|
class page_tree;
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <util/pointers.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "frame_allocator.h"
|
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "frame_allocator.h"
|
||||||
#include "page_table.h"
|
#include "page_table.h"
|
||||||
|
|
||||||
using memory::page_offset;
|
using mem::frame_size;
|
||||||
|
using mem::linear_offset;
|
||||||
using level = page_table::level;
|
using level = page_table::level;
|
||||||
|
|
||||||
free_page_header * page_table::s_page_cache = nullptr;
|
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);
|
uint64_t parent = entry(l - 1);
|
||||||
if (parent & 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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -138,11 +139,11 @@ page_table::iterator::ensure_table(level l)
|
|||||||
if (check_table(l)) return;
|
if (check_table(l)) return;
|
||||||
|
|
||||||
page_table *table = page_table::get_table_page();
|
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);
|
uint64_t &parent = entry(l - 1);
|
||||||
flag flags = table_flags;
|
flag flags = table_flags;
|
||||||
if (m_index[0] < memory::pml4e_kernel)
|
if (m_index[0] < arch::kernel_root_index)
|
||||||
flags |= flag::user;
|
flags |= flag::user;
|
||||||
|
|
||||||
m_table[unsigned(l)] = table;
|
m_table[unsigned(l)] = table;
|
||||||
@@ -161,14 +162,14 @@ page_table::get(int i, uint16_t *flags) const
|
|||||||
if (flags)
|
if (flags)
|
||||||
*flags = entry & 0xfffull;
|
*flags = entry & 0xfffull;
|
||||||
|
|
||||||
return reinterpret_cast<page_table *>((entry & ~0xfffull) + page_offset);
|
return reinterpret_cast<page_table *>((entry & ~0xfffull) + linear_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
page_table::set(int i, page_table *p, uint16_t flags)
|
page_table::set(int i, page_table *p, uint16_t flags)
|
||||||
{
|
{
|
||||||
entries[i] =
|
entries[i] =
|
||||||
(reinterpret_cast<uint64_t>(p) - page_offset) |
|
(reinterpret_cast<uint64_t>(p) - linear_offset) |
|
||||||
(flags & 0xfff);
|
(flags & 0xfff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@ page_table::get_table_page()
|
|||||||
--s_cache_count;
|
--s_cache_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(page, 0, memory::frame_size);
|
memset(page, 0, frame_size);
|
||||||
return reinterpret_cast<page_table*>(page);
|
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");
|
kassert(phys, "Got physical page 0 as a page table");
|
||||||
|
|
||||||
free_page_header *start =
|
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)
|
for (int i = 0; i < n - 1; ++i)
|
||||||
offset_pointer(start, i * memory::frame_size)
|
util::offset_pointer(start, i * frame_size)
|
||||||
->next = offset_pointer(start, (i+1) * memory::frame_size);
|
->next = util::offset_pointer(start, (i+1) * frame_size);
|
||||||
|
|
||||||
free_page_header *end =
|
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;
|
end->next = s_page_cache;
|
||||||
s_page_cache = start;
|
s_page_cache = start;
|
||||||
@@ -238,14 +239,14 @@ void
|
|||||||
page_table::free(page_table::level l)
|
page_table::free(page_table::level l)
|
||||||
{
|
{
|
||||||
unsigned last = l == level::pml4
|
unsigned last = l == level::pml4
|
||||||
? memory::pml4e_kernel
|
? arch::kernel_root_index
|
||||||
: memory::table_entries;
|
: arch::table_entries;
|
||||||
|
|
||||||
frame_allocator &fa = frame_allocator::get();
|
frame_allocator &fa = frame_allocator::get();
|
||||||
for (unsigned i = 0; i < last; ++i) {
|
for (unsigned i = 0; i < last; ++i) {
|
||||||
if (!is_present(i)) continue;
|
if (!is_present(i)) continue;
|
||||||
if (is_page(l, i)) {
|
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);
|
fa.free(entries[i] & ~0xfffull, count);
|
||||||
} else {
|
} else {
|
||||||
get(i)->free(l + 1);
|
get(i)->free(l + 1);
|
||||||
@@ -261,7 +262,7 @@ page_table::dump(page_table::level lvl, bool recurse)
|
|||||||
console *cons = console::get();
|
console *cons = console::get();
|
||||||
|
|
||||||
cons->printf("\nLevel %d page table @ %lx:\n", lvl, this);
|
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];
|
uint64_t ent = entries[i];
|
||||||
|
|
||||||
if ((ent & 0x1) == 0)
|
if ((ent & 0x1) == 0)
|
||||||
@@ -275,11 +276,11 @@ page_table::dump(page_table::level lvl, bool recurse)
|
|||||||
|
|
||||||
else
|
else
|
||||||
cons->printf(" %3d: %016lx -> Level %d table at %016lx\n",
|
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) {
|
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))
|
if (is_large_page(lvl, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
/// Helper structures for dealing with page tables.
|
/// Helper structures for dealing with page tables.
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <arch/memory.h>
|
||||||
#include <util/spinlock.h>
|
#include <util/spinlock.h>
|
||||||
#include <enum_bitfields.h>
|
#include <enum_bitfields.h>
|
||||||
#include <kernel_memory.h>
|
|
||||||
|
|
||||||
struct free_page_header;
|
struct free_page_header;
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ struct page_table
|
|||||||
/// Print this table to the debug console.
|
/// Print this table to the debug console.
|
||||||
void dump(level lvl = level::pml4, bool recurse = true);
|
void dump(level lvl = level::pml4, bool recurse = true);
|
||||||
|
|
||||||
uint64_t entries[memory::table_entries];
|
uint64_t entries[arch::table_entries];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <arch/memory.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "frame_allocator.h"
|
#include "frame_allocator.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "page_tree.h"
|
#include "page_tree.h"
|
||||||
|
|
||||||
// Page tree levels map the following parts of an offset. Note the xxx part of
|
// 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 max_level = 5;
|
||||||
static constexpr unsigned bits_per_level = 6;
|
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 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; }
|
inline int index_for(uint64_t off, uint8_t level) { return (off >> level_shift(level)) & 0x3full; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include "pointer_manipulation.h"
|
|
||||||
#include "symbol_table.h"
|
#include "symbol_table.h"
|
||||||
|
|
||||||
namespace panicking {
|
namespace panicking {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "counted.h"
|
#include <util/counted.h>
|
||||||
|
|
||||||
namespace panicking {
|
namespace panicking {
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
const void *m_data;
|
const void *m_data;
|
||||||
counted<entry const> m_entries;
|
util::counted<entry const> m_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace panicking
|
} // namespace panicking
|
||||||
|
|||||||
@@ -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
|
// Walk the extended capabilities list
|
||||||
uint8_t next = m_base[13] & 0xff;
|
uint8_t next = m_base[13] & 0xff;
|
||||||
while (next) {
|
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;
|
next = cap->next;
|
||||||
log::debug(logs::device, " - found PCI cap type %02x", cap->id);
|
log::debug(logs::device, " - found PCI cap type %02x", cap->id);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// PCI devices and groups
|
/// PCI devices and groups
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "memory.h"
|
#include <util/pointers.h>
|
||||||
|
|
||||||
struct pci_group;
|
struct pci_group;
|
||||||
enum class isr : uint8_t;
|
enum class isr : uint8_t;
|
||||||
@@ -126,7 +126,7 @@ struct pci_group
|
|||||||
/// \returns A pointer to the memory-mapped configuration registers
|
/// \returns A pointer to the memory-mapped configuration registers
|
||||||
inline uint32_t * base_for(uint8_t bus, uint8_t device, uint8_t func)
|
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);
|
pci_device::bus_addr(bus, device, func) << 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "msr.h"
|
#include "msr.h"
|
||||||
#include "objects/channel.h"
|
#include "objects/channel.h"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "frame_allocator.h"
|
#include "frame_allocator.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "objects/endpoint.h"
|
#include "objects/endpoint.h"
|
||||||
#include "objects/thread.h"
|
#include "objects/thread.h"
|
||||||
#include "objects/system.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
|
// 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))
|
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);
|
vm_flags vmf = (static_cast<vm_flags>(flags) & vm_flags::driver_mask);
|
||||||
construct_handle<vm_area_fixed>(area, phys, size, vmf);
|
construct_handle<vm_area_fixed>(area, phys, size, vmf);
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "kernel_memory.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "objects/vm_area.h"
|
#include "objects/vm_area.h"
|
||||||
#include "tss.h"
|
#include "tss.h"
|
||||||
|
|
||||||
@@ -45,8 +45,8 @@ void
|
|||||||
TSS::create_ist_stacks(uint8_t ist_entries)
|
TSS::create_ist_stacks(uint8_t ist_entries)
|
||||||
{
|
{
|
||||||
extern vm_area_guarded &g_kernel_stacks;
|
extern vm_area_guarded &g_kernel_stacks;
|
||||||
using memory::frame_size;
|
using mem::frame_size;
|
||||||
using memory::kernel_stack_pages;
|
using mem::kernel_stack_pages;
|
||||||
constexpr size_t stack_bytes = kernel_stack_pages * frame_size;
|
constexpr size_t stack_bytes = kernel_stack_pages * frame_size;
|
||||||
|
|
||||||
for (unsigned ist = 1; ist < 8; ++ist) {
|
for (unsigned ist = 1; ist < 8; ++ist) {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "kernel_memory.h"
|
#include <arch/memory.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "frame_allocator.h"
|
#include "frame_allocator.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "memory.h"
|
||||||
#include "objects/process.h"
|
#include "objects/process.h"
|
||||||
#include "objects/thread.h"
|
#include "objects/thread.h"
|
||||||
#include "objects/vm_area.h"
|
#include "objects/vm_area.h"
|
||||||
@@ -42,8 +43,8 @@ vm_space::vm_space() :
|
|||||||
m_pml4 = page_table::get_table_page();
|
m_pml4 = page_table::get_table_page();
|
||||||
page_table *kpml4 = kernel_space().m_pml4;
|
page_table *kpml4 = kernel_space().m_pml4;
|
||||||
|
|
||||||
memset(m_pml4, 0, memory::frame_size/2);
|
memset(m_pml4, 0, mem::frame_size/2);
|
||||||
for (unsigned i = memory::pml4e_kernel; i < memory::table_entries; ++i)
|
for (unsigned i = arch::kernel_root_index; i < arch::table_entries; ++i)
|
||||||
m_pml4->entries[i] = kpml4->entries[i];
|
m_pml4->entries[i] = kpml4->entries[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ void
|
|||||||
vm_space::remove_area(vm_area *area)
|
vm_space::remove_area(vm_area *area)
|
||||||
{
|
{
|
||||||
area->remove_from(this);
|
area->remove_from(this);
|
||||||
clear(*area, 0, memory::page_count(area->size()));
|
clear(*area, 0, mem::page_count(area->size()));
|
||||||
area->handle_release();
|
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))
|
if (!find_vma(vma, from) || !source.find_vma(vma, from))
|
||||||
return;
|
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 dit {to, m_pml4};
|
||||||
page_table::iterator sit {from, source.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
|
void
|
||||||
vm_space::page_in(const vm_area &vma, uintptr_t offset, uintptr_t phys, size_t count)
|
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};
|
util::scoped_lock lock {m_lock};
|
||||||
|
|
||||||
uintptr_t base = 0;
|
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
|
void
|
||||||
vm_space::clear(const vm_area &vma, uintptr_t offset, size_t count, bool free)
|
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};
|
util::scoped_lock lock {m_lock};
|
||||||
|
|
||||||
uintptr_t base = 0;
|
uintptr_t base = 0;
|
||||||
@@ -248,13 +249,13 @@ vm_space::active() const
|
|||||||
{
|
{
|
||||||
uintptr_t pml4 = 0;
|
uintptr_t pml4 = 0;
|
||||||
__asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (pml4) );
|
__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
|
void
|
||||||
vm_space::activate() const
|
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;
|
uintptr_t p = reinterpret_cast<uintptr_t>(m_pml4) & phys_mask;
|
||||||
__asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (p) );
|
__asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (p) );
|
||||||
}
|
}
|
||||||
@@ -264,7 +265,7 @@ vm_space::initialize_tcb(TCB &tcb)
|
|||||||
{
|
{
|
||||||
tcb.pml4 =
|
tcb.pml4 =
|
||||||
reinterpret_cast<uintptr_t>(m_pml4) &
|
reinterpret_cast<uintptr_t>(m_pml4) &
|
||||||
~memory::page_offset;
|
~mem::linear_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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
|
// TODO: iterate page mappings and continue copying. For now i'm blindly
|
||||||
// assuming both buffers are fully contained within single pages
|
// assuming both buffers are fully contained within single pages
|
||||||
memcpy(
|
memcpy(
|
||||||
memory::to_virtual<void>((*dit & ~0xfffull) | (ito & 0xffful)),
|
mem::to_virtual<void>((*dit & ~0xfffull) | (ito & 0xffful)),
|
||||||
memory::to_virtual<void>((*sit & ~0xfffull) | (ifrom & 0xffful)),
|
mem::to_virtual<void>((*sit & ~0xfffull) | (ifrom & 0xffful)),
|
||||||
length);
|
length);
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
|
|||||||
12
src/libraries/bootproto/bootproto.module
Normal file
12
src/libraries/bootproto/bootproto.module
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# vim: ft=python
|
||||||
|
|
||||||
|
bp = module("bootproto",
|
||||||
|
kind = "lib",
|
||||||
|
includes = [ "include" ],
|
||||||
|
sources = [
|
||||||
|
])
|
||||||
|
|
||||||
|
from os.path import join
|
||||||
|
|
||||||
|
layout = join(source_root, "definitions/memory_layout.csv")
|
||||||
|
bp.add_input("include/bootproto/memory.h.cog", deps=[layout])
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
/// \file bootproto/init.h
|
||||||
|
/// Data structures for initializing the init server
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "counted.h"
|
#include <util/counted.h>
|
||||||
|
|
||||||
namespace kernel {
|
namespace bootproto {
|
||||||
namespace init {
|
|
||||||
|
|
||||||
enum class module_type : uint8_t {
|
enum class module_type : uint8_t {
|
||||||
none,
|
none,
|
||||||
@@ -52,7 +53,7 @@ struct video_mode
|
|||||||
struct module_framebuffer :
|
struct module_framebuffer :
|
||||||
public module
|
public module
|
||||||
{
|
{
|
||||||
buffer framebuffer;
|
util::buffer framebuffer;
|
||||||
video_mode mode;
|
video_mode mode;
|
||||||
fb_type type;
|
fb_type type;
|
||||||
};
|
};
|
||||||
@@ -64,5 +65,4 @@ struct modules_page
|
|||||||
uintptr_t next;
|
uintptr_t next;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace init
|
} // namespace bootproto
|
||||||
} // namespace kernel
|
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
/// \file bootproto/kernel.h
|
||||||
|
/// Data structures for initializing the kernel
|
||||||
|
|
||||||
#include <stdalign.h>
|
#include <stdalign.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "counted.h"
|
|
||||||
|
|
||||||
namespace kernel {
|
#include <util/counted.h>
|
||||||
namespace init {
|
|
||||||
|
|
||||||
constexpr uint32_t args_magic = 'j6ia'; // "jsix init args"
|
namespace bootproto {
|
||||||
|
|
||||||
|
constexpr uint32_t args_magic = 'j6bp'; // "jsix boot protocol"
|
||||||
constexpr uint16_t args_version = 1;
|
constexpr uint16_t args_version = 1;
|
||||||
|
|
||||||
constexpr uint64_t header_magic = 0x4c454e52454b366aull; // 'j6KERNEL'
|
constexpr uint64_t header_magic = 0x4c454e52454b366aull; // 'j6KERNEL'
|
||||||
@@ -32,7 +34,7 @@ struct program_section {
|
|||||||
struct program {
|
struct program {
|
||||||
uintptr_t entrypoint;
|
uintptr_t entrypoint;
|
||||||
uintptr_t phys_base;
|
uintptr_t phys_base;
|
||||||
counted<program_section> sections;
|
util::counted<program_section> sections;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class mem_type : uint32_t {
|
enum class mem_type : uint32_t {
|
||||||
@@ -120,9 +122,9 @@ struct args
|
|||||||
boot_flags flags;
|
boot_flags flags;
|
||||||
|
|
||||||
void *pml4;
|
void *pml4;
|
||||||
counted<void> page_tables;
|
util::counted<void> page_tables;
|
||||||
counted<mem_entry> mem_map;
|
util::counted<mem_entry> mem_map;
|
||||||
counted<frame_block> frame_blocks;
|
util::counted<frame_block> frame_blocks;
|
||||||
|
|
||||||
program *kernel;
|
program *kernel;
|
||||||
program *init;
|
program *init;
|
||||||
@@ -153,7 +155,6 @@ struct header
|
|||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
using entrypoint = __attribute__((sysv_abi)) void (*)(init::args *);
|
using entrypoint = __attribute__((sysv_abi)) void (*)(args *);
|
||||||
|
|
||||||
} // namespace init
|
} // namespace bootproto
|
||||||
} // namespace kernel
|
|
||||||
24
src/libraries/bootproto/include/bootproto/memory.h.cog
Normal file
24
src/libraries/bootproto/include/bootproto/memory.h.cog
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
// vim: ft=cpp
|
||||||
|
|
||||||
|
/// \file bootproto/memory.h
|
||||||
|
/// Import memory layout constants necessary for boot
|
||||||
|
|
||||||
|
namespace bootproto {
|
||||||
|
namespace mem {
|
||||||
|
|
||||||
|
/*[[[cog code generation
|
||||||
|
from os.path import join
|
||||||
|
from memory import Layout
|
||||||
|
|
||||||
|
layout = Layout(join(definitions_path, "memory_layout.csv"))
|
||||||
|
|
||||||
|
for region in layout.regions:
|
||||||
|
if region.shared:
|
||||||
|
cog.outl(f"constexpr uintptr_t {region.name}_offset = 0x{region.start:x};")
|
||||||
|
|
||||||
|
]]]*/
|
||||||
|
///[[[end]]]
|
||||||
|
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace bootproto
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
module("elf",
|
module("elf",
|
||||||
kind = "lib",
|
kind = "lib",
|
||||||
includes = [ "include" ],
|
includes = [ "include" ],
|
||||||
|
deps = [ "util" ],
|
||||||
sources = [
|
sources = [
|
||||||
"file.cpp",
|
"file.cpp",
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "elf/file.h"
|
#include <elf/file.h>
|
||||||
#include "elf/headers.h"
|
#include <elf/headers.h>
|
||||||
#include "pointer_manipulation.h"
|
|
||||||
|
|
||||||
static const uint32_t expected_magic = 0x464c457f; // "\x7f" "ELF"
|
static const uint32_t expected_magic = 0x464c457f; // "\x7f" "ELF"
|
||||||
|
|
||||||
@@ -8,9 +7,14 @@ namespace elf {
|
|||||||
|
|
||||||
inline const file_header * fh(const void *data) { return reinterpret_cast<const file_header*>(data); }
|
inline const file_header * fh(const void *data) { return reinterpret_cast<const file_header*>(data); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const T *convert(const void *data, size_t offset) {
|
||||||
|
return reinterpret_cast<const T*>(util::offset_pointer(data, offset));
|
||||||
|
}
|
||||||
|
|
||||||
file::file(const void *data, size_t size) :
|
file::file(const void *data, size_t size) :
|
||||||
m_programs(offset_ptr<program_header>(data, fh(data)->ph_offset), fh(data)->ph_entsize, fh(data)->ph_num),
|
m_programs(convert<program_header>(data, fh(data)->ph_offset), fh(data)->ph_entsize, fh(data)->ph_num),
|
||||||
m_sections(offset_ptr<section_header>(data, fh(data)->sh_offset), fh(data)->sh_entsize, fh(data)->sh_num),
|
m_sections(convert<section_header>(data, fh(data)->sh_offset), fh(data)->sh_entsize, fh(data)->sh_num),
|
||||||
m_data(data),
|
m_data(data),
|
||||||
m_size(size)
|
m_size(size)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "pointer_manipulation.h"
|
#include <util/pointers.h>
|
||||||
|
|
||||||
namespace elf {
|
namespace elf {
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ template <typename T>
|
|||||||
class subheaders
|
class subheaders
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator = const_offset_iterator<T>;
|
using iterator = util::const_offset_iterator<T>;
|
||||||
|
|
||||||
subheaders(const T *start, size_t size, unsigned count) :
|
subheaders(const T *start, size_t size, unsigned count) :
|
||||||
m_start(start), m_size(size), m_count(count) {}
|
m_start(start), m_size(size), m_count(count) {}
|
||||||
@@ -22,9 +22,9 @@ public:
|
|||||||
inline size_t size() const { return m_size; }
|
inline size_t size() const { return m_size; }
|
||||||
inline unsigned count() const { return m_count; }
|
inline unsigned count() const { return m_count; }
|
||||||
|
|
||||||
inline const T & operator [] (int i) const { return *offset_ptr<T>(m_start, m_size*i); }
|
inline const T & operator [] (int i) const { return *util::offset_pointer<T>(m_start, m_size*i); }
|
||||||
inline const iterator begin() const { return iterator(m_start, m_size); }
|
inline const iterator begin() const { return iterator(m_start, m_size); }
|
||||||
inline const iterator end() const { return offset_ptr<T>(m_start, m_size*m_count); }
|
inline const iterator end() const { return util::offset_pointer(m_start, m_size*m_count); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const T *m_start;
|
const T *m_start;
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
/// \file counted.h
|
/// \file counted.h
|
||||||
/// Definition of the `counted` template class
|
/// Definition of the `counted` template class
|
||||||
|
|
||||||
#include "pointer_manipulation.h"
|
#include <util/pointers.h>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
/// A pointer and an associated count. Memory pointed to is not managed.
|
/// A pointer and an associated count. Memory pointed to is not managed.
|
||||||
/// Depending on the usage, the count may be size or number of elements.
|
/// Depending on the usage, the count may be size or number of elements.
|
||||||
@@ -26,13 +28,13 @@ struct counted
|
|||||||
inline iterator begin() { return iterator(pointer, sizeof(T)); }
|
inline iterator begin() { return iterator(pointer, sizeof(T)); }
|
||||||
|
|
||||||
/// Return an iterator to the end of the array
|
/// Return an iterator to the end of the array
|
||||||
inline iterator end() { return offset_ptr<T>(pointer, sizeof(T)*count); }
|
inline iterator end() { return offset_pointer<T>(pointer, sizeof(T)*count); }
|
||||||
|
|
||||||
/// Return an iterator to the beginning of the array
|
/// Return an iterator to the beginning of the array
|
||||||
inline const_iterator begin() const { return const_iterator(pointer, sizeof(T)); }
|
inline const_iterator begin() const { return const_iterator(pointer, sizeof(T)); }
|
||||||
|
|
||||||
/// Return an iterator to the end of the array
|
/// Return an iterator to the end of the array
|
||||||
inline const_iterator end() const { return offset_ptr<const T>(pointer, sizeof(T)*count); }
|
inline const_iterator end() const { return offset_pointer<const T>(pointer, sizeof(T)*count); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Specialize for `void` which cannot be indexed or iterated
|
/// Specialize for `void` which cannot be indexed or iterated
|
||||||
@@ -44,3 +46,5 @@ struct counted<void>
|
|||||||
};
|
};
|
||||||
|
|
||||||
using buffer = counted<void>;
|
using buffer = counted<void>;
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
@@ -2,11 +2,23 @@
|
|||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
|
/// Reverse the order of bytes in a 32 bit integer
|
||||||
constexpr uint32_t
|
constexpr uint32_t
|
||||||
byteswap(uint32_t x)
|
byteswap32(uint32_t x) {
|
||||||
{
|
|
||||||
return ((x >> 24) & 0x000000ff) | ((x >> 8) & 0x0000ff00)
|
return ((x >> 24) & 0x000000ff) | ((x >> 8) & 0x0000ff00)
|
||||||
| ((x << 8) & 0x00ff0000) | ((x << 24) & 0xff000000);
|
| ((x << 8) & 0x00ff0000) | ((x << 24) & 0xff000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do a simple byte-wise checksum of an area of memory. The area
|
||||||
|
/// summed will be the bytes at indicies [off, len).
|
||||||
|
/// \arg p The start of the memory region
|
||||||
|
/// \arg len The number of bytes in the region
|
||||||
|
/// \arg off An optional offset into the region
|
||||||
|
uint8_t checksum(const void *p, size_t len, size_t off = 0) {
|
||||||
|
uint8_t sum = 0;
|
||||||
|
const uint8_t *c = reinterpret_cast<const uint8_t *>(p);
|
||||||
|
for (size_t i = off; i < len; ++i) sum += c[i];
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,37 @@
|
|||||||
/// \file pointer_manipulation.h
|
/// \file pointers.h
|
||||||
/// Helper functions and types for doing type-safe byte-wise pointer math.
|
/// Helper functions and types for doing type-safe byte-wise pointer math.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
/// Return a pointer offset from `input` by `offset` bytes.
|
/// Return a pointer offset from `input` by `offset` bytes.
|
||||||
/// \tparam T Cast the return value to a pointer to `T`
|
/// \arg input The original pointer
|
||||||
/// \tparam S The type pointed to by the `input` pointer
|
/// \arg offset Offset `input` by this many bytes
|
||||||
template <typename T, typename S>
|
template <typename T>
|
||||||
inline T* offset_ptr(S* input, ptrdiff_t offset) {
|
inline T* offset_pointer(T* input, ptrdiff_t offset) {
|
||||||
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(input) + offset);
|
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(input) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a pointer with the given bits masked out
|
||||||
|
/// \arg input The original pointer
|
||||||
|
/// \arg mask A bitmask of bits to clear from p
|
||||||
|
/// \returns The masked pointer
|
||||||
|
template <typename T>
|
||||||
|
inline T* mask_pointer(T *input, uintptr_t mask) {
|
||||||
|
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(input) & ~mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a value of type T from a location in memory
|
||||||
|
/// \arg p The location in memory to read
|
||||||
|
/// \returns The value at the given location cast to T
|
||||||
|
template <typename T>
|
||||||
|
inline T read_from(const void *p) {
|
||||||
|
return *reinterpret_cast<const T *>(p);
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterator for an array of `const T` whose size is known at runtime
|
/// Iterator for an array of `const T` whose size is known at runtime
|
||||||
/// \tparam T Type of the objects in the array, whose size might not be
|
/// \tparam T Type of the objects in the array, whose size might not be
|
||||||
/// what is returned by sizeof(T).
|
/// what is returned by sizeof(T).
|
||||||
@@ -25,7 +45,7 @@ public:
|
|||||||
/// which creates an effectively constant iterator.
|
/// which creates an effectively constant iterator.
|
||||||
const_offset_iterator(T const *t, size_t off=0) : m_t(t), m_off(off) {}
|
const_offset_iterator(T const *t, size_t off=0) : m_t(t), m_off(off) {}
|
||||||
|
|
||||||
const T * operator++() { m_t = offset_ptr<T>(m_t, m_off); return m_t; }
|
const T * operator++() { m_t = offset_pointer(m_t, m_off); return m_t; }
|
||||||
const T * operator++(int) { T* tmp = m_t; operator++(); return tmp; }
|
const T * operator++(int) { T* tmp = m_t; operator++(); return tmp; }
|
||||||
|
|
||||||
bool operator==(T* p) const { return p == m_t; }
|
bool operator==(T* p) const { return p == m_t; }
|
||||||
@@ -55,7 +75,7 @@ public:
|
|||||||
/// which creates an effectively constant iterator.
|
/// which creates an effectively constant iterator.
|
||||||
offset_iterator(T *t, size_t off=0) : m_t(t), m_off(off) {}
|
offset_iterator(T *t, size_t off=0) : m_t(t), m_off(off) {}
|
||||||
|
|
||||||
T * operator++() { m_t = offset_ptr<T>(m_t, m_off); return m_t; }
|
T * operator++() { m_t = offset_pointer(m_t, m_off); return m_t; }
|
||||||
T * operator++(int) { T* tmp = m_t; operator++(); return tmp; }
|
T * operator++(int) { T* tmp = m_t; operator++(); return tmp; }
|
||||||
|
|
||||||
bool operator==(T *p) const { return p == m_t; }
|
bool operator==(T *p) const { return p == m_t; }
|
||||||
@@ -72,3 +92,4 @@ private:
|
|||||||
size_t m_off;
|
size_t m_off;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
init = module("srv.init",
|
init = module("srv.init",
|
||||||
targets = [ "user" ],
|
targets = [ "user" ],
|
||||||
deps = [ "libc", "elf" ],
|
deps = [ "libc", "elf", "bootproto" ],
|
||||||
sources = [
|
sources = [
|
||||||
"loader.cpp",
|
"loader.cpp",
|
||||||
"main.cpp",
|
"main.cpp",
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <bootproto/init.h>
|
||||||
#include <elf/file.h>
|
#include <elf/file.h>
|
||||||
#include <elf/headers.h>
|
#include <elf/headers.h>
|
||||||
#include <j6/errors.h>
|
#include <j6/errors.h>
|
||||||
#include <j6/flags.h>
|
#include <j6/flags.h>
|
||||||
#include <j6/syscalls.h>
|
#include <j6/syscalls.h>
|
||||||
#include <init_args.h>
|
|
||||||
#include <enum_bitfields.h>
|
#include <enum_bitfields.h>
|
||||||
|
|
||||||
using kernel::init::module_flags;
|
using bootproto::module_flags;
|
||||||
using kernel::init::module_program;
|
using bootproto::module_program;
|
||||||
|
|
||||||
extern j6_handle_t handle_self;
|
extern j6_handle_t handle_self;
|
||||||
extern j6_handle_t handle_system;
|
extern j6_handle_t handle_system;
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
/// \file loader.h
|
/// \file loader.h
|
||||||
/// Routines for loading and starting other programs
|
/// Routines for loading and starting other programs
|
||||||
|
|
||||||
namespace kernel {
|
namespace bootproto {
|
||||||
namespace init {
|
|
||||||
struct module_program;
|
struct module_program;
|
||||||
}}
|
}
|
||||||
|
|
||||||
bool load_program(const kernel::init::module_program &prog, char *err_msg);
|
bool load_program(const bootproto::module_program &prog, char *err_msg);
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <j6/syscalls.h>
|
#include <j6/syscalls.h>
|
||||||
#include <init_args.h>
|
#include <bootproto/init.h>
|
||||||
|
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
|
|
||||||
using kernel::init::module;
|
using bootproto::module;
|
||||||
using kernel::init::module_type;
|
using bootproto::module_type;
|
||||||
using kernel::init::module_program;
|
using bootproto::module_program;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
int main(int, const char **);
|
int main(int, const char **);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
|
|
||||||
using module = kernel::init::module;
|
using module = bootproto::module;
|
||||||
using modules_page = kernel::init::modules_page;
|
using modules_page = bootproto::modules_page;
|
||||||
|
|
||||||
static const modules_page *
|
static const modules_page *
|
||||||
get_page(const module *mod)
|
get_page(const module *mod)
|
||||||
@@ -20,7 +20,7 @@ const module *
|
|||||||
module_iterator::operator++()
|
module_iterator::operator++()
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
m_mod = offset_ptr<module>(m_mod, m_mod->mod_length);
|
m_mod = util::offset_pointer(m_mod, m_mod->mod_length);
|
||||||
|
|
||||||
if (m_mod->mod_type == type::none) {
|
if (m_mod->mod_type == type::none) {
|
||||||
// We've reached the end of a page, see if there's another
|
// We've reached the end of a page, see if there's another
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
/// \file modules.h
|
/// \file modules.h
|
||||||
/// Routines for loading initial argument modules
|
/// Routines for loading initial argument modules
|
||||||
|
|
||||||
|
#include <bootproto/init.h>
|
||||||
#include <j6/types.h>
|
#include <j6/types.h>
|
||||||
#include <init_args.h>
|
#include <util/pointers.h>
|
||||||
#include <pointer_manipulation.h>
|
|
||||||
|
|
||||||
|
|
||||||
class module_iterator
|
class module_iterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using type = kernel::init::module_type;
|
using type = bootproto::module_type;
|
||||||
using module = kernel::init::module;
|
using module = bootproto::module;
|
||||||
|
|
||||||
module_iterator(const module *m, type t = type::none) :
|
module_iterator(const module *m, type t = type::none) :
|
||||||
m_mod {m}, m_type {t} {}
|
m_mod {m}, m_type {t} {}
|
||||||
@@ -40,7 +40,7 @@ private:
|
|||||||
class modules
|
class modules
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using type = kernel::init::module_type;
|
using type = bootproto::module_type;
|
||||||
using iterator = module_iterator;
|
using iterator = module_iterator;
|
||||||
|
|
||||||
static modules load_modules(
|
static modules load_modules(
|
||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
iterator end() const { return nullptr; }
|
iterator end() const { return nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using module = kernel::init::module;
|
using module = bootproto::module;
|
||||||
|
|
||||||
modules(const module* root) : m_root {root} {}
|
modules(const module* root) : m_root {root} {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user