refactor: implement generated ABI

This commit is contained in:
Mark Poliakov 2024-03-12 13:46:24 +02:00
parent ca4e50d464
commit 1c0212238a
12 changed files with 847 additions and 1871 deletions

1055
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,8 @@ authors = ["Mark Poliakov <mark@alnyan.me>"]
opt-level = 3 opt-level = 3
[dependencies] [dependencies]
abi-lib = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" }
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
vfs = { path = "lib/vfs" } vfs = { path = "lib/vfs" }
device-api = { path = "lib/device-api", features = ["derive"] } device-api = { path = "lib/device-api", features = ["derive"] }
@ -70,6 +72,11 @@ acpi-system = { git = "https://github.com/alnyan/acpi-system.git" }
ygg_driver_nvme = { path = "driver/block/nvme" } ygg_driver_nvme = { path = "driver/block/nvme" }
kernel-arch-x86_64 = { path = "arch/x86_64" } kernel-arch-x86_64 = { path = "arch/x86_64" }
[build-dependencies]
prettyplease = "0.2.15"
yggdrasil-abi-def = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi-def.git" }
abi-generator = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" }
[features] [features]
default = ["fb_console"] default = ["fb_console"]
fb_console = [] fb_console = []

View File

@ -1,10 +1,16 @@
use std::{ use std::{
env, env, fs,
io::{self, Write}, io::{self, Write},
path::PathBuf, path::{Path, PathBuf},
process::Command, process::Command,
}; };
use abi_generator::{
abi::{ty::TypeWidth, AbiBuilder},
syntax::UnwrapFancy,
TargetEnv,
};
fn build_x86_64() { fn build_x86_64() {
const DEFAULT_8086_AS: &str = "nasm"; const DEFAULT_8086_AS: &str = "nasm";
const AP_BOOTSTRAP_S: &str = "src/arch/x86_64/boot/ap_boot.S"; const AP_BOOTSTRAP_S: &str = "src/arch/x86_64/boot/ap_boot.S";
@ -33,9 +39,31 @@ fn build_x86_64() {
} }
} }
fn generate_syscall_dispatcher<P: AsRef<Path>>(out_dir: P) {
let abi: AbiBuilder = AbiBuilder::from_string(
yggdrasil_abi_def::ABI_FILE,
TargetEnv {
thin_pointer_width: TypeWidth::U64,
fat_pointer_width: TypeWidth::U128,
},
)
.unwrap_fancy("");
let generated_dispatcher = out_dir.as_ref().join("generated_dispatcher.rs");
let file = prettyplease::unparse(
&abi.emit_syscall_dispatcher("handle_syscall", "impls")
.unwrap_fancy(""),
);
fs::write(generated_dispatcher, file.as_bytes()).unwrap();
}
fn main() { fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
generate_syscall_dispatcher(&out_dir);
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
match arch.as_str() { match arch.as_str() {

View File

@ -148,8 +148,8 @@ impl<A: BlockAllocator> MemoryFilesystem<A> {
let node = self.make_path(&root, path, FileType::Directory, false)?; let node = self.make_path(&root, path, FileType::Directory, false)?;
assert_eq!(node.ty(), hdr.node_kind()); assert_eq!(node.ty(), hdr.node_kind());
let uid = UserId::from(usize::from(&hdr.uid) as u32); let uid = unsafe { UserId::from_raw(usize::from(&hdr.uid) as u32) };
let gid = GroupId::from(usize::from(&hdr.gid) as u32); let gid = unsafe { GroupId::from_raw(usize::from(&hdr.gid) as u32) };
let mode = convert_mode(usize::from(&hdr.mode))?; let mode = convert_mode(usize::from(&hdr.mode))?;
let access = unsafe { AccessToken::authorized() }; let access = unsafe { AccessToken::authorized() };

View File

@ -10,6 +10,7 @@ libk-util = { path = "../libk-util" }
libk-mm = { path = "../libk-mm" } libk-mm = { path = "../libk-mm" }
libk-device = { path = "../libk-device" } libk-device = { path = "../libk-device" }
kernel-arch = { path = "../../arch" } kernel-arch = { path = "../../arch" }
abi-lib = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" }
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }

View File

@ -1,5 +1,6 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use abi_lib::SyscallRegister;
use alloc::{ use alloc::{
collections::BTreeMap, collections::BTreeMap,
string::String, string::String,
@ -17,7 +18,7 @@ use libk_util::{
}, },
}; };
use yggdrasil_abi::{ use yggdrasil_abi::{
error::{Error, SyscallResult}, error::Error,
process::{ExitCode, Signal, ThreadSpawnOptions}, process::{ExitCode, Signal, ThreadSpawnOptions},
}; };
@ -247,12 +248,12 @@ impl<PM: ProcessManager<Process = Self>, IO: ProcessIo> ProcessImpl<PM, IO> {
let src_thread = Thread::current(); let src_thread = Thread::current();
let src_process = src_thread.process::<PM>(); let src_process = src_thread.process::<PM>();
let rax = src_process let value = src_process
.fork_inner(frame) .fork_inner(frame)
.map(|ProcessId(p)| p as u32) .map(|ProcessId(p)| p as u32)
.into_syscall_result(); .into_syscall_register();
frame.set_return_value(rax as _); frame.set_return_value(value as _);
} }
/// Replaces the process address space with a new one, loaded from the specified program /// Replaces the process address space with a new one, loaded from the specified program

View File

@ -11,7 +11,7 @@ use aarch64_cpu::{
}; };
use abi::{ use abi::{
process::{Signal, SignalEntryData}, process::{Signal, SignalEntryData},
syscall::SyscallFunction, SyscallFunction,
}; };
use kernel_arch::{task::TaskFrame, Architecture, ArchitectureImpl}; use kernel_arch::{task::TaskFrame, Architecture, ArchitectureImpl};
use kernel_arch_aarch64::context::ExceptionFrame; use kernel_arch_aarch64::context::ExceptionFrame;

View File

@ -93,6 +93,7 @@ impl Platform for AArch64 {
} }
unsafe fn reset(&self) -> ! { unsafe fn reset(&self) -> ! {
loop {}
if let Some(reset) = self.reset.try_get() { if let Some(reset) = self.reset.try_get() {
reset.reset() reset.reset()
} else { } else {

View File

@ -2,7 +2,7 @@
use core::arch::global_asm; use core::arch::global_asm;
use abi::{process::SignalEntryData, syscall::SyscallFunction}; use abi::{process::SignalEntryData, SyscallFunction};
use kernel_arch::task::TaskFrame; use kernel_arch::task::TaskFrame;
use kernel_arch_x86_64::{ use kernel_arch_x86_64::{
context::SyscallFrame, context::SyscallFrame,
@ -23,6 +23,7 @@ fn syscall_inner(frame: &mut SyscallFrame) {
return; return;
} }
} }
// FIXME: Fork is temporarily disabled
if frame.rax == usize::from(SyscallFunction::Fork) as u64 { if frame.rax == usize::from(SyscallFunction::Fork) as u64 {
unsafe { unsafe {
ProcessImpl::raw_fork(frame); ProcessImpl::raw_fork(frame);

View File

@ -25,7 +25,8 @@
inline_const, inline_const,
maybe_uninit_uninit_array, maybe_uninit_uninit_array,
const_maybe_uninit_uninit_array, const_maybe_uninit_uninit_array,
never_type never_type,
trace_macros
)] )]
#![allow( #![allow(
clippy::new_without_default, clippy::new_without_default,

View File

@ -1,26 +1,19 @@
use abi::io::RawFd; use libk_thread::{mem::ForeignPointer, thread::Thread};
use libk_thread::{
mem::{validate_user_region, ForeignPointer},
thread::Thread,
};
use yggdrasil_abi::error::Error; use yggdrasil_abi::error::Error;
// XXX pub(super) fn ref_const<'a, T: Sized>(addr: usize) -> Result<&'a T, Error> {
pub(super) fn arg_buffer_ref<'a>(base: usize, len: usize) -> Result<&'a [u8], Error> {
let proc = Thread::current(); let proc = Thread::current();
validate_user_region(proc.address_space(), base, len, false)?; let ptr = addr as *const T;
Ok(unsafe { core::slice::from_raw_parts(base as *const u8, len) }) unsafe { ptr.validate_user_ptr(proc.address_space()) }
}
pub(super) fn ref_mut<'a, T: Sized>(addr: usize) -> Result<&'a mut T, Error> {
let proc = Thread::current();
let ptr = addr as *mut T;
unsafe { ptr.validate_user_mut(proc.address_space()) }
} }
pub(super) fn arg_buffer_mut<'a>(base: usize, len: usize) -> Result<&'a mut [u8], Error> { pub(super) fn str_ref<'a>(base: usize, len: usize) -> Result<&'a str, Error> {
let proc = Thread::current(); let slice = slice_ref(base, len)?;
validate_user_region(proc.address_space(), base, len, true)?;
Ok(unsafe { core::slice::from_raw_parts_mut(base as *mut u8, len) })
}
pub(super) fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error> {
let slice = arg_buffer_ref(base, len)?;
if slice.contains(&0) { if slice.contains(&0) {
warnln!("User-supplied string contains NUL characters"); warnln!("User-supplied string contains NUL characters");
return Err(Error::InvalidArgument); return Err(Error::InvalidArgument);
@ -28,31 +21,13 @@ pub(super) fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error
Ok(core::str::from_utf8(slice).unwrap()) Ok(core::str::from_utf8(slice).unwrap())
} }
pub(super) fn arg_user_ref<'a, T: Sized>(addr: usize) -> Result<&'a T, Error> { pub(super) fn slice_ref<'a, T: Sized>(base: usize, count: usize) -> Result<&'a [T], Error> {
let proc = Thread::current(); let proc = Thread::current();
let ptr = addr as *const T; let ptr = base as *const T;
unsafe { ptr.validate_user_ptr(proc.address_space()) } unsafe { ptr.validate_user_slice(count, proc.address_space()) }
} }
pub(super) fn slice_mut<'a, T: Sized>(base: usize, count: usize) -> Result<&'a mut [T], Error> {
pub(super) fn arg_user_mut<'a, T: Sized>(addr: usize) -> Result<&'a mut T, Error> {
let proc = Thread::current();
let ptr = addr as *mut T;
unsafe { ptr.validate_user_mut(proc.address_space()) }
}
pub(super) fn arg_user_slice_mut<'a, T: Sized>(
base: usize,
count: usize,
) -> Result<&'a mut [T], Error> {
let proc = Thread::current(); let proc = Thread::current();
let ptr = base as *mut T; let ptr = base as *mut T;
unsafe { ptr.validate_user_slice_mut(count, proc.address_space()) } unsafe { ptr.validate_user_slice_mut(count, proc.address_space()) }
} }
pub(super) fn arg_option_fd(raw: u32) -> Option<RawFd> {
if raw == u32::MAX {
None
} else {
Some(RawFd(raw))
}
}

File diff suppressed because it is too large Load Diff