3 Commits

Author SHA1 Message Date
Justin C. Miller
dd73cf833f Change initrd 'executable' bool to type enum. 2019-10-10 23:09:40 -07:00
Justin C. Miller
71fe3d733b Add the VDSO to the initrd 2019-10-10 00:14:46 -07:00
Justin C. Miller
991b13424e Initial building of the vdso.
Not actually integrating with the kernel yet.
2019-10-09 22:29:45 -07:00
17 changed files with 195 additions and 27 deletions

View File

@@ -8,6 +8,11 @@
# # initial application for the kernel to execute # # initial application for the kernel to execute
# # on startup # # on startup
[[files]]
dest = "vdso.so"
source = "host/libvdso.so"
type = "vdso"
[[files]] [[files]]
dest = "screenfont.psf" dest = "screenfont.psf"
source = "../assets/fonts/tamsyn8x16r.psf" source = "../assets/fonts/tamsyn8x16r.psf"
@@ -15,9 +20,9 @@ source = "../assets/fonts/tamsyn8x16r.psf"
[[files]] [[files]]
dest = "nulldrv1" dest = "nulldrv1"
source = "user/nulldrv" source = "user/nulldrv"
executable = true type = "executable"
[[files]] [[files]]
dest = "nulldrv2" dest = "nulldrv2"
source = "user/nulldrv" source = "user/nulldrv"
executable = true type = "executable"

View File

@@ -9,6 +9,7 @@ modules:
- elf - elf
- initrd - initrd
- kutil - kutil
- vdso
includes: includes:
- src/kernel - src/kernel
source: source:
@@ -64,6 +65,16 @@ modules:
- src/boot/reloc.cpp - src/boot/reloc.cpp
- src/boot/utility.cpp - src/boot/utility.cpp
vdso:
kind: exe
target: host
output: libvdso.so
extra:
- src/arch/x86_64/vdso.ld
source:
- src/vdso/syscalls.cpp
- src/vdso/overrides.cpp
nulldrv: nulldrv:
kind: exe kind: exe
target: user target: user

View File

@@ -43,6 +43,7 @@ ccflags = $
$warnflags $warnflags
asflags = $ asflags = $
-I${srcroot}/src/include $
-DVERSION_MAJOR={{ version_major }} $ -DVERSION_MAJOR={{ version_major }} $
-DVERSION_MINOR={{ version_minor }} $ -DVERSION_MINOR={{ version_minor }} $
-DVERSION_PATCH={{ version_patch }} $ -DVERSION_PATCH={{ version_patch }} $
@@ -186,6 +187,7 @@ build $builddir/fatroot/efi/boot/bootx64.efi : cp $builddir/boot/boot.efi
name = bootloader to FAT image name = bootloader to FAT image
build $builddir/fatroot/initrd.img : makerd ${srcroot}/assets/initrd.toml | $ build $builddir/fatroot/initrd.img : makerd ${srcroot}/assets/initrd.toml | $
${builddir}/host/libvdso.so $
${builddir}/native/makerd $ ${builddir}/native/makerd $
${builddir}/user/nulldrv ${builddir}/user/nulldrv

View File

@@ -0,0 +1,9 @@
{% extends "exe.default.j2" %}
{% block variables %}
{{ super() }}
ccflags = $ccflags -fPIC -mcmodel=large
ldflags = $ldflags -shared -znotext -T ${srcroot}/src/arch/x86_64/vdso.ld
{% endblock %}
# vim: ft=ninja et ts=4 sts=4 sw=4

73
src/arch/x86_64/vdso.ld Normal file
View File

@@ -0,0 +1,73 @@
PHDRS {
headers PT_PHDR FLAGS(4) FILEHDR PHDRS ;
rodata PT_LOAD FLAGS(4) ;
text PT_LOAD FLAGS(5) ;
dynamic PT_DYNAMIC FLAGS(4) ;
note PT_NOTE ;
eh_frame PT_GNU_EH_FRAME ;
}
SECTIONS {
. = SIZEOF_HEADERS;
/DISCARD/ : {
*(.got*)
*(.plt*)
*(.note.*)
*(.hash*)
*(.debug*)
}
.illegal.relocations : {
*(.rel*)
}
.illegal.writeable : {
*(.data*)
*(.bss*)
}
.rodata : {
*(.rodata*)
} :rodata
.dynamic : {
*(.dynamic)
} :dynamic
.dynsym : {
*(.dynsym*)
} :rodata :dynamic
.dynstr : {
*(.dynstr*)
} :rodata :dynamic
.gnu.hash : {
*(.gnu.hash*)
} :rodata
.eh_frame_hdr : {
__eh_frame_start = .;
KEEP(*(.eh_frame))
__eh_frame_end = .;
KEEP(*(.eh_frame_hdr))
} :eh_frame
.shstrtab : {
*(.shstrtab)
}
.text ALIGN(0x1000) : {
*(.text*)
*(.init*)
*(.fini*)
. = ALIGN(0x1000);
} :text
ASSERT(SIZEOF(.illegal.relocations) == 0,
"Code has introduced relocations into the VDSO")
ASSERT(SIZEOF(.illegal.writeable) == 0,
"Code has introduced writeable data into the VDSO")
}

View File

@@ -2,8 +2,8 @@ SYSCALL(0x00, object_noop, void)
SYSCALL(0x01, object_wait, j6_handle_t, j6_signal_t, j6_signal_t *) SYSCALL(0x01, object_wait, j6_handle_t, j6_signal_t, j6_signal_t *)
SYSCALL(0x11, process_exit, int64_t) SYSCALL(0x11, process_exit, int64_t)
SYSCALL(0x12, process_fork, pid_t*) //SYSCALL(0x12, process_fork, j6_koid_t*)
SYSCALL(0x13, process_getpid, pid_t*) //SYSCALL(0x13, process_getpid, j6_koid_t*)
SYSCALL(0x14, process_log, const char *) SYSCALL(0x14, process_log, const char *)
SYSCALL(0x15, process_pause, void) SYSCALL(0x15, process_pause, void)
SYSCALL(0x16, process_sleep, uint64_t) SYSCALL(0x16, process_sleep, uint64_t)

View File

@@ -108,7 +108,11 @@ kernel_main(kernel_args *header)
initrd::disk ird(header->initrd, heap); initrd::disk ird(header->initrd, heap);
log::info(logs::boot, "initrd loaded with %d files.", ird.files().count()); log::info(logs::boot, "initrd loaded with %d files.", ird.files().count());
for (auto &f : ird.files()) for (auto &f : ird.files())
log::info(logs::boot, " %s%s (%d bytes).", f.executable() ? "*" : "", f.name(), f.size()); log::info(logs::boot, " %s%s (%d bytes).",
f.type() == initrd::file_type::executable ? "*" :
f.type() == initrd::file_type::vdso ? "^" : "",
f.name(),
f.size());
/* /*
page_manager::get()->dump_pml4(nullptr, 0); page_manager::get()->dump_pml4(nullptr, 0);
@@ -163,7 +167,7 @@ kernel_main(kernel_args *header)
sched->create_kernel_task(-1, logger_task); sched->create_kernel_task(-1, logger_task);
for (auto &f : ird.files()) { for (auto &f : ird.files()) {
if (f.executable()) if (f.type() == initrd::file_type::executable)
sched->load_process(f.name(), f.data(), f.size()); sched->load_process(f.name(), f.data(), f.size());
} }

View File

@@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
namespace initrd {
enum class file_type : uint8_t
{
unknown,
executable,
vdso
};
} // namespace initrd

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "kutil/enum_bitfields.h" #include "kutil/enum_bitfields.h"
#include "initrd/file_type.h"
namespace initrd { namespace initrd {
@@ -18,10 +19,8 @@ struct disk_header
uint8_t reserved[3]; uint8_t reserved[3];
} __attribute__ ((packed)); } __attribute__ ((packed));
enum class file_flags : uint8_t
enum class file_flags : uint16_t
{ {
executable = 0x01
}; };
struct file_header struct file_header
@@ -29,10 +28,10 @@ struct file_header
uint32_t offset; uint32_t offset;
uint32_t length; uint32_t length;
uint16_t name_offset; uint16_t name_offset;
file_type type;
file_flags flags; file_flags flags;
} __attribute__ ((packed)); } __attribute__ ((packed));
} // namepsace initrd } // namepsace initrd
IS_BITFIELD(initrd::disk_flags); IS_BITFIELD(initrd::disk_flags);
IS_BITFIELD(initrd::file_flags);

View File

@@ -5,6 +5,7 @@
#include <stdint.h> #include <stdint.h>
#include "kutil/vector.h" #include "kutil/vector.h"
#include "initrd/file_type.h"
// File format: // File format:
// 1x disk_header // 1x disk_header
@@ -33,8 +34,8 @@ public:
/// Get a pointer to the file data /// Get a pointer to the file data
const void * data() const; const void * data() const;
/// Whether this file is an executable /// Type of file
bool executable() const; file_type type() const;
private: private:
const file_header *m_header; const file_header *m_header;

View File

@@ -16,11 +16,7 @@ file::file(const file_header *header, const void *start) :
const char * file::name() const { return m_name; } const char * file::name() const { return m_name; }
const size_t file::size() const { return m_header->length; } const size_t file::size() const { return m_header->length; }
const void * file::data() const { return m_data; } const void * file::data() const { return m_data; }
file_type file::type() const { return m_header->type; }
bool
file::executable() const {
return bitfield_has(m_header->flags, file_flags::executable);
}
disk::disk(const void *start, kutil::allocator &alloc) : disk::disk(const void *start, kutil::allocator &alloc) :

View File

@@ -1,10 +1,10 @@
#include "entry.h" #include "entry.h"
entry::entry(const std::string &in, const std::string &out, bool executable) : entry::entry(const std::string &in, const std::string &out, initrd::file_type type) :
m_in(in), m_in(in),
m_out(out), m_out(out),
m_file(in, std::ios_base::binary), m_file(in, std::ios_base::binary),
m_exec(executable) m_type(type)
{ {
m_file.seekg(0, std::ios_base::end); m_file.seekg(0, std::ios_base::end);
m_size = m_file.tellg(); m_size = m_file.tellg();

View File

@@ -1,17 +1,18 @@
#pragma once #pragma once
#include <string> #include <string>
#include <fstream> #include <fstream>
#include "initrd/headers.h"
class entry class entry
{ {
public: public:
entry(const std::string &in, const std::string &out, bool executable = false); entry(const std::string &in, const std::string &out, initrd::file_type type);
inline const std::string & in() const { return m_in; } inline const std::string & in() const { return m_in; }
inline const std::string & out() const { return m_out; } inline const std::string & out() const { return m_out; }
inline const std::ifstream & file() const { return m_file; } inline const std::ifstream & file() const { return m_file; }
inline bool executable() const { return m_exec; } inline initrd::file_type type() const { return m_type; }
inline size_t size() const { return m_size; } inline size_t size() const { return m_size; }
inline bool good() const { return m_file.good(); } inline bool good() const { return m_file.good(); }
@@ -20,6 +21,6 @@ private:
std::string m_out; std::string m_out;
std::ifstream m_file; std::ifstream m_file;
size_t m_size; size_t m_size;
bool m_exec; initrd::file_type m_type;
}; };

View File

@@ -43,9 +43,15 @@ int main(int argc, char **argv)
return 1; return 1;
} }
auto exec = file->get_as<bool>("executable").value_or(false); auto type_name = file->get_as<std::string>("type").value_or("unknown");
initrd::file_type type = initrd::file_type::unknown;
if (type_name == "executable") {
type = initrd::file_type::executable;
} else if (type_name == "vdso") {
type = initrd::file_type::vdso;
}
entries.emplace_back(*source, *dest, exec); entries.emplace_back(*source, *dest, type);
const entry &e = entries.back(); const entry &e = entries.back();
if (!e.good()) { if (!e.good()) {
@@ -92,9 +98,7 @@ int main(int argc, char **argv)
fheader.offset = file_offset; fheader.offset = file_offset;
fheader.length = e.size(); fheader.length = e.size();
fheader.name_offset = name_offset; fheader.name_offset = name_offset;
fheader.type = e.type();
if (e.executable())
fheader.flags |= initrd::file_flags::executable;
out.write( out.write(
reinterpret_cast<const char *>(&fheader), reinterpret_cast<const char *>(&fheader),

17
src/vdso/overrides.cpp Normal file
View File

@@ -0,0 +1,17 @@
#include <j6/errors.h>
#include <j6/types.h>
#include "vdso_internal.h"
extern "C" {
j6_status_t j6_object_noop() {
// Skip the kernel
return j6_status_ok;
}
// An example of overriding a weak default symbol with a custom function
j6_status_t j6_object_wait(j6_handle_t target, j6_signal_t signals, j6_signal_t *triggered) {
return __sys_j6_object_wait(target, signals, triggered);
}
}

17
src/vdso/syscalls.cpp Normal file
View File

@@ -0,0 +1,17 @@
#include <j6/errors.h>
#include <j6/types.h>
#include "vdso_internal.h"
#define SYSCALL(num, name, ...) \
j6_status_t __sys_j6_##name (__VA_ARGS__) { \
j6_status_t result = 0; \
__asm__ __volatile__ ( "syscall" : "=a"(result) : "a"(num) ); \
return result; \
} \
j6_status_t j6_ ## name(__VA_ARGS__) __weak_alias("__sys_j6_" #name);
extern "C" {
#include "syscalls.inc"
}
#undef SYSCALL

16
src/vdso/vdso_internal.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
/// \file vdso_internal.h
/// VDSO syscall forward-declares and linker utils
#define __weak_alias(name) __attribute__((weak, alias(name)));
#define __local __attribute__((__visibility__("hidden")))
#define SYSCALL(num, name, ...) \
j6_status_t __sys_j6_ ## name (__VA_ARGS__) __local; \
extern "C" {
#include "syscalls.inc"
}
#undef SYSCALL