mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 05:46:48 +00:00
add derive procedural macro for pod
This commit is contained in:
parent
895e5c340b
commit
6e56458e52
10
src/Cargo.lock
generated
10
src/Cargo.lock
generated
@ -97,6 +97,15 @@ dependencies = [
|
|||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kxos-frame-pod-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kxos-pci"
|
name = "kxos-pci"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -114,6 +123,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"kxos-frame",
|
"kxos-frame",
|
||||||
|
"kxos-frame-pod-derive",
|
||||||
"kxos-pci",
|
"kxos-pci",
|
||||||
"kxos-virtio",
|
"kxos-virtio",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -17,6 +17,7 @@ members = [
|
|||||||
"kxos-pci",
|
"kxos-pci",
|
||||||
"kxos-virtio",
|
"kxos-virtio",
|
||||||
"kxos-util",
|
"kxos-util",
|
||||||
|
"kxos-frame-pod-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata.bootloader]
|
[package.metadata.bootloader]
|
||||||
|
14
src/kxos-frame-pod-derive/Cargo.toml
Normal file
14
src/kxos-frame-pod-derive/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "kxos-frame-pod-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
proc-macro2 = "1.0"
|
||||||
|
quote = "1.0"
|
||||||
|
syn = "1.0.90"
|
49
src/kxos-frame-pod-derive/src/lib.rs
Normal file
49
src/kxos-frame-pod-derive/src/lib.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields};
|
||||||
|
|
||||||
|
#[proc_macro_derive(Pod)]
|
||||||
|
pub fn derive_pod(input_token: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let input = parse_macro_input!(input_token as DeriveInput);
|
||||||
|
expand_derive_pod(input).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expand_derive_pod(input: DeriveInput) -> TokenStream {
|
||||||
|
let ident = input.ident;
|
||||||
|
let fields = match input.data {
|
||||||
|
Data::Struct(DataStruct { fields, .. }) => match fields {
|
||||||
|
Fields::Named(fields_named) => fields_named.named,
|
||||||
|
Fields::Unnamed(fields_unnamed) => fields_unnamed.unnamed,
|
||||||
|
Fields::Unit => panic!("derive pod does not work for struct with unit field"),
|
||||||
|
},
|
||||||
|
// Panic on compilation time if one tries to derive pod for enum or union.
|
||||||
|
// It may not be a good idea, but works now.
|
||||||
|
_ => panic!("derive pod only works for struct now."),
|
||||||
|
};
|
||||||
|
|
||||||
|
// deal with generics
|
||||||
|
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
|
let pod_where_predicates = fields
|
||||||
|
.into_iter()
|
||||||
|
.map(|field| {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
quote! {
|
||||||
|
#field_ty: ::kxos_frame::Pod
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// if where_clause is none, we should add a `where` word manually.
|
||||||
|
if where_clause.is_none() {
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
unsafe impl #impl_generics ::kxos_frame::Pod #type_generics for #ident where #(#pod_where_predicates),* {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
unsafe impl #impl_generics ::kxos_frame::Pod #type_generics for #ident #where_clause, #(#pod_where_predicates),* {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
kxos-frame = {path = "../kxos-frame"}
|
kxos-frame = {path = "../kxos-frame"}
|
||||||
|
kxos-frame-pod-derive = {path = "../kxos-frame-pod-derive"}
|
||||||
kxos-pci = {path="../kxos-pci"}
|
kxos-pci = {path="../kxos-pci"}
|
||||||
kxos-virtio = {path="../kxos-virtio"}
|
kxos-virtio = {path="../kxos-virtio"}
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ mod memory;
|
|||||||
mod process;
|
mod process;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
mod util;
|
mod util;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate kxos_frame_pod_derive;
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
driver::init();
|
driver::init();
|
||||||
|
@ -33,7 +33,7 @@ pub fn load_elf_to_vm_space<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// copy bytes from user space of current process. The bytes len is the len of dest.
|
/// copy bytes from user space of current process. The bytes len is the len of dest.
|
||||||
pub fn copy_bytes_from_user(src: Vaddr, dest: &mut [u8]) {
|
pub fn read_bytes_from_user(src: Vaddr, dest: &mut [u8]) {
|
||||||
let current = Process::current();
|
let current = Process::current();
|
||||||
let vm_space = current
|
let vm_space = current
|
||||||
.vm_space()
|
.vm_space()
|
||||||
@ -42,7 +42,7 @@ pub fn copy_bytes_from_user(src: Vaddr, dest: &mut [u8]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// copy val (Plain of Data type) from user space of current process.
|
/// copy val (Plain of Data type) from user space of current process.
|
||||||
pub fn copy_val_from_user<T: Pod>(src: Vaddr) -> T {
|
pub fn read_val_from_user<T: Pod>(src: Vaddr) -> T {
|
||||||
let current = Process::current();
|
let current = Process::current();
|
||||||
let vm_space = current
|
let vm_space = current
|
||||||
.vm_space()
|
.vm_space()
|
||||||
@ -60,10 +60,10 @@ pub fn write_bytes_to_user(dest: Vaddr, src: &[u8]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// write val (Plain of Data type) to user space of current process.
|
/// write val (Plain of Data type) to user space of current process.
|
||||||
pub fn write_val_to_user<T: Pod>(dest: Vaddr, val: T) {
|
pub fn write_val_to_user<T: Pod>(dest: Vaddr, val: &T) {
|
||||||
let current = Process::current();
|
let current = Process::current();
|
||||||
let vm_space = current
|
let vm_space = current
|
||||||
.vm_space()
|
.vm_space()
|
||||||
.expect("[Internal error]Current should have vm space to write val to user");
|
.expect("[Internal error]Current should have vm space to write val to user");
|
||||||
vm_space.write_val(dest, &val).expect("write val failed");
|
vm_space.write_val(dest, val).expect("write val failed");
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{memory::copy_val_from_user, syscall::SYS_FUTEX};
|
use crate::{memory::read_val_from_user, syscall::SYS_FUTEX};
|
||||||
|
|
||||||
use super::SyscallResult;
|
use super::SyscallResult;
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
@ -340,7 +340,7 @@ impl FutexKey {
|
|||||||
pub fn load_val(&self) -> i32 {
|
pub fn load_val(&self) -> i32 {
|
||||||
// FIXME: how to implement a atomic load?
|
// FIXME: how to implement a atomic load?
|
||||||
warn!("implement an atomic load");
|
warn!("implement an atomic load");
|
||||||
copy_val_from_user(self.0)
|
read_val_from_user(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addr(&self) -> Vaddr {
|
pub fn addr(&self) -> Vaddr {
|
||||||
|
@ -4,7 +4,7 @@ use alloc::ffi::CString;
|
|||||||
use kxos_frame::{debug, vm::Vaddr};
|
use kxos_frame::{debug, vm::Vaddr};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
memory::{copy_bytes_from_user, write_bytes_to_user},
|
memory::{read_bytes_from_user, write_bytes_to_user},
|
||||||
process::Process,
|
process::Process,
|
||||||
syscall::SYS_READLINK,
|
syscall::SYS_READLINK,
|
||||||
};
|
};
|
||||||
@ -32,7 +32,7 @@ pub fn do_sys_readlink(filename_ptr: Vaddr, user_buf_ptr: Vaddr, user_buf_len: u
|
|||||||
|
|
||||||
let mut filename_buffer = [0u8; MAX_FILENAME_LEN];
|
let mut filename_buffer = [0u8; MAX_FILENAME_LEN];
|
||||||
let current = Process::current();
|
let current = Process::current();
|
||||||
copy_bytes_from_user(filename_ptr, &mut filename_buffer);
|
read_bytes_from_user(filename_ptr, &mut filename_buffer);
|
||||||
let filename = CStr::from_bytes_until_nul(&filename_buffer).expect("Invalid filename");
|
let filename = CStr::from_bytes_until_nul(&filename_buffer).expect("Invalid filename");
|
||||||
debug!("filename = {:?}", filename);
|
debug!("filename = {:?}", filename);
|
||||||
if filename == CString::new("/proc/self/exe").unwrap().as_c_str() {
|
if filename == CString::new("/proc/self/exe").unwrap().as_c_str() {
|
||||||
|
@ -5,10 +5,13 @@ use kxos_frame::{debug, vm::Vaddr};
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
memory::write_bytes_to_user,
|
memory::write_val_to_user,
|
||||||
syscall::{SyscallResult, SYS_UNAME},
|
syscall::{SyscallResult, SYS_UNAME},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The values are used to fool glibc. Since glibc will check the version and os name
|
||||||
|
// We don't use lazy static to generate a static UTS_NAME is because lazy static will create a new struct, which does not inherent the trait.å
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// used to fool glibc
|
/// used to fool glibc
|
||||||
static ref SYS_NAME: CString = CString::new("Linux").unwrap();
|
static ref SYS_NAME: CString = CString::new("Linux").unwrap();
|
||||||
@ -31,6 +34,7 @@ lazy_static! {
|
|||||||
|
|
||||||
const UTS_FIELD_LEN: usize = 65;
|
const UTS_FIELD_LEN: usize = 65;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct UtsName {
|
struct UtsName {
|
||||||
sysname: [u8; UTS_FIELD_LEN],
|
sysname: [u8; UTS_FIELD_LEN],
|
||||||
@ -71,11 +75,6 @@ pub fn do_sys_uname(old_uname_addr: Vaddr) -> usize {
|
|||||||
debug!("uts name size: {}", core::mem::size_of::<UtsName>());
|
debug!("uts name size: {}", core::mem::size_of::<UtsName>());
|
||||||
debug!("uts name align: {}", core::mem::align_of::<UtsName>());
|
debug!("uts name align: {}", core::mem::align_of::<UtsName>());
|
||||||
|
|
||||||
write_bytes_to_user(old_uname_addr, &UTS_NAME.sysname);
|
write_val_to_user(old_uname_addr, &*UTS_NAME);
|
||||||
write_bytes_to_user(old_uname_addr + UTS_FIELD_LEN, &UTS_NAME.nodename);
|
|
||||||
write_bytes_to_user(old_uname_addr + UTS_FIELD_LEN * 2, &UTS_NAME.release);
|
|
||||||
write_bytes_to_user(old_uname_addr + UTS_FIELD_LEN * 3, &UTS_NAME.version);
|
|
||||||
write_bytes_to_user(old_uname_addr + UTS_FIELD_LEN * 4, &UTS_NAME.machine);
|
|
||||||
write_bytes_to_user(old_uname_addr + UTS_FIELD_LEN * 5, &UTS_NAME.domainname);
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ pub fn sys_wait4(wait_pid: u64, exit_status_ptr: u64, wait_options: u64) -> Sysc
|
|||||||
let process_filter = ProcessFilter::from_wait_pid(wait_pid as _);
|
let process_filter = ProcessFilter::from_wait_pid(wait_pid as _);
|
||||||
let (return_pid, exit_code) = wait_child_exit(process_filter, wait_options);
|
let (return_pid, exit_code) = wait_child_exit(process_filter, wait_options);
|
||||||
if return_pid != 0 && exit_status_ptr != 0 {
|
if return_pid != 0 && exit_status_ptr != 0 {
|
||||||
write_val_to_user(exit_status_ptr as _, exit_code);
|
write_val_to_user(exit_status_ptr as _, &exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
SyscallResult::Return(return_pid as _)
|
SyscallResult::Return(return_pid as _)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use kxos_frame::{debug, info};
|
use kxos_frame::{debug, info};
|
||||||
|
|
||||||
use crate::{memory::copy_bytes_from_user, syscall::SYS_WRITE};
|
use crate::{memory::read_bytes_from_user, syscall::SYS_WRITE};
|
||||||
|
|
||||||
use super::SyscallResult;
|
use super::SyscallResult;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ pub fn sys_write(fd: u64, user_buf_ptr: u64, user_buf_len: u64) -> SyscallResult
|
|||||||
|
|
||||||
if fd == STDOUT || fd == STDERR {
|
if fd == STDOUT || fd == STDERR {
|
||||||
let mut buffer = vec![0u8; user_buf_len as usize];
|
let mut buffer = vec![0u8; user_buf_len as usize];
|
||||||
copy_bytes_from_user(user_buf_ptr as usize, &mut buffer);
|
read_bytes_from_user(user_buf_ptr as usize, &mut buffer);
|
||||||
let content = alloc::str::from_utf8(buffer.as_slice()).expect("Invalid content"); // TODO: print content
|
let content = alloc::str::from_utf8(buffer.as_slice()).expect("Invalid content"); // TODO: print content
|
||||||
if fd == STDOUT {
|
if fd == STDOUT {
|
||||||
info!("Message from user mode: {:?}", content);
|
info!("Message from user mode: {:?}", content);
|
||||||
|
@ -2,7 +2,7 @@ use alloc::vec;
|
|||||||
use kxos_frame::{debug, info, vm::Vaddr};
|
use kxos_frame::{debug, info, vm::Vaddr};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
memory::{copy_bytes_from_user, copy_val_from_user},
|
memory::{read_bytes_from_user, read_val_from_user},
|
||||||
syscall::SYS_WRITEV,
|
syscall::SYS_WRITEV,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -10,6 +10,8 @@ use super::SyscallResult;
|
|||||||
|
|
||||||
const IOVEC_MAX: usize = 256;
|
const IOVEC_MAX: usize = 256;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, Copy, Pod)]
|
||||||
pub struct IoVec {
|
pub struct IoVec {
|
||||||
base: Vaddr,
|
base: Vaddr,
|
||||||
len: usize,
|
len: usize,
|
||||||
@ -27,12 +29,13 @@ pub fn do_sys_writev(fd: u64, io_vec_addr: Vaddr, io_vec_count: usize) -> usize
|
|||||||
debug!("io_vec_counter = 0x{:x}", io_vec_count);
|
debug!("io_vec_counter = 0x{:x}", io_vec_count);
|
||||||
let mut write_len = 0;
|
let mut write_len = 0;
|
||||||
for i in 0..io_vec_count {
|
for i in 0..io_vec_count {
|
||||||
let base = copy_val_from_user::<usize>(io_vec_addr + i * 8);
|
let io_vec = read_val_from_user::<IoVec>(io_vec_addr + i * 8);
|
||||||
let len = copy_val_from_user::<usize>(io_vec_addr + i * 8 + 8);
|
let base = io_vec.base;
|
||||||
|
let len = io_vec.len;
|
||||||
debug!("base = 0x{:x}", base);
|
debug!("base = 0x{:x}", base);
|
||||||
debug!("len = {}", len);
|
debug!("len = {}", len);
|
||||||
let mut buffer = vec![0u8; len];
|
let mut buffer = vec![0u8; len];
|
||||||
copy_bytes_from_user(base, &mut buffer);
|
read_bytes_from_user(base, &mut buffer);
|
||||||
let content = alloc::str::from_utf8(&buffer).unwrap();
|
let content = alloc::str::from_utf8(&buffer).unwrap();
|
||||||
write_len += len;
|
write_len += len;
|
||||||
if fd == 1 {
|
if fd == 1 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user