mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[kernel] Add test mode, controlled by manifest
The manifest can now supply a list of boot flags, including "test". Those get turned into the bootproto::args::flags field by the bootloader. The kernel takes those and uses the test flag to control enabling syscalls with the new "test" attribute, like the new test_finish syscall, which lets automated tests call back to the kernel to shut down the system.
This commit is contained in:
@@ -41,7 +41,8 @@ bootconfig::bootconfig(util::buffer data, uefi::boot_services *bs)
|
||||
data += 1; // reserved byte
|
||||
uint16_t num_programs = *util::read<uint16_t>(data);
|
||||
uint16_t num_data = *util::read<uint16_t>(data);
|
||||
data += 2; // reserved short
|
||||
|
||||
m_flags = *util::read<uint16_t>(data);
|
||||
|
||||
read_descriptor(m_kernel, data);
|
||||
read_descriptor(m_init, data);
|
||||
|
||||
@@ -28,12 +28,14 @@ public:
|
||||
/// Constructor. Loads bootconfig from the given buffer.
|
||||
bootconfig(util::buffer data, uefi::boot_services *bs);
|
||||
|
||||
inline const descriptor & kernel() { return m_kernel; }
|
||||
inline const descriptor & init() { return m_init; }
|
||||
inline uint16_t flags() const { return m_flags; }
|
||||
inline const descriptor & kernel() const { return m_kernel; }
|
||||
inline const descriptor & init() const { return m_init; }
|
||||
descriptors programs() { return m_programs; }
|
||||
descriptors data() { return m_data; }
|
||||
|
||||
private:
|
||||
uint16_t m_flags;
|
||||
descriptor m_kernel;
|
||||
descriptor m_init;
|
||||
descriptors m_programs;
|
||||
|
||||
@@ -77,6 +77,7 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image,
|
||||
|
||||
args->kernel = loader::load_program(disk, bc.kernel(), true);
|
||||
args->init = loader::load_program(disk, bc.init());
|
||||
args->flags = static_cast<bootproto::boot_flags>(bc.flags());
|
||||
|
||||
namespace bits = util::bits;
|
||||
using bootproto::desc_flags;
|
||||
|
||||
@@ -98,8 +98,6 @@ bsp_late_init()
|
||||
asm ("mov %%cr4, %0" : "=r"(cr4));
|
||||
uint64_t efer = rdmsr(msr::ia32_efer);
|
||||
log::debug(logs::boot, "Control regs: cr0:%lx cr4:%lx efer:%lx", cr0, cr4, efer);
|
||||
|
||||
syscall_initialize();
|
||||
}
|
||||
|
||||
cpu_data *
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "objects/vm_area.h"
|
||||
#include "scheduler.h"
|
||||
#include "smp.h"
|
||||
#include "syscall.h"
|
||||
#include "sysconf.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -55,6 +56,10 @@ kernel_main(bootproto::args *args)
|
||||
|
||||
bsp_late_init();
|
||||
|
||||
using bootproto::boot_flags;
|
||||
bool enable_test = util::bits::has(args->flags, boot_flags::test);
|
||||
syscall_initialize(enable_test);
|
||||
|
||||
device_manager &devices = device_manager::get();
|
||||
devices.parse_acpi(args->acpi_table);
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ syscall_invalid(uint64_t call)
|
||||
}
|
||||
|
||||
void
|
||||
syscall_initialize()
|
||||
syscall_initialize(bool enable_test)
|
||||
{
|
||||
memset(&syscall_registry, 0, sizeof(syscall_registry));
|
||||
|
||||
@@ -77,8 +77,17 @@ syscall_initialize()
|
||||
else:
|
||||
name = method.name
|
||||
|
||||
cog.outl(f"syscall_registry[{id}] = reinterpret_cast<uintptr_t>(syscalls::_syscall_verify_{name});")
|
||||
cog.outl(f"""log::debug(logs::syscall, "Enabling syscall {id:02x} as {name}");""")
|
||||
indent = ""
|
||||
if "test" in method.options:
|
||||
cog.outl("if (enable_test) {")
|
||||
indent = " "
|
||||
|
||||
cog.outl(f"{indent}syscall_registry[{id}] = reinterpret_cast<uintptr_t>(syscalls::_syscall_verify_{name});")
|
||||
cog.outl(f"""{indent}log::debug(logs::syscall, "Enabling syscall {id:02x} as {name}");""")
|
||||
|
||||
if "test" in method.options:
|
||||
cog.outl("}")
|
||||
|
||||
cog.outl("")
|
||||
]]]*/
|
||||
//[[[end]]]
|
||||
|
||||
@@ -17,5 +17,5 @@ cog.outl(f"constexpr size_t num_syscalls = {len(syscalls.methods)};")
|
||||
]]]*/
|
||||
/// [[[end]]]
|
||||
|
||||
void syscall_initialize();
|
||||
void syscall_initialize(bool enable_test);
|
||||
extern "C" void syscall_enable();
|
||||
|
||||
@@ -36,6 +36,14 @@ noop()
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
[[ noreturn ]] j6_status_t
|
||||
test_finish(uint32_t exit_code)
|
||||
{
|
||||
// Tell QEMU to exit
|
||||
asm ( "out %0, %1" :: "a"(exit_code), "Nd"(0xf4) );
|
||||
while (1) asm ("hlt");
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
system_get_log(system *self, void *buffer, size_t *buffer_len)
|
||||
{
|
||||
|
||||
@@ -114,8 +114,10 @@ struct frame_block
|
||||
|
||||
enum class boot_flags : uint16_t {
|
||||
none = 0x0000,
|
||||
debug = 0x0001
|
||||
debug = 0x0001,
|
||||
test = 0x0002,
|
||||
};
|
||||
is_bitfield(boot_flags);
|
||||
|
||||
struct args
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user