Compare commits
3 Commits
feature/mu
...
vdso
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd73cf833f | ||
|
|
71fe3d733b | ||
|
|
991b13424e |
@@ -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"
|
||||||
|
|||||||
11
modules.yaml
11
modules.yaml
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
9
scripts/templates/exe.vdso.j2
Normal file
9
scripts/templates/exe.vdso.j2
Normal 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
73
src/arch/x86_64/vdso.ld
Normal 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")
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
src/libraries/initrd/include/initrd/file_type.h
Normal file
13
src/libraries/initrd/include/initrd/file_type.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace initrd {
|
||||||
|
|
||||||
|
enum class file_type : uint8_t
|
||||||
|
{
|
||||||
|
unknown,
|
||||||
|
executable,
|
||||||
|
vdso
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace initrd
|
||||||
@@ -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);
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) :
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
17
src/vdso/overrides.cpp
Normal 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
17
src/vdso/syscalls.cpp
Normal 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
16
src/vdso/vdso_internal.h
Normal 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
|
||||||
|
|
||||||
Reference in New Issue
Block a user