ソースを参照

Merge branch 'trap-abstraction' into remove-cpp

greatbridf 8 ヶ月 前
コミット
f1f1f6ac24

+ 29 - 11
Cargo.lock

@@ -28,7 +28,15 @@ version = "0.1.0"
 dependencies = [
  "cfg-if",
  "eonix_mm",
- "percpu-macros",
+]
+
+[[package]]
+name = "arch_macros"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -127,11 +135,28 @@ dependencies = [
  "bitflags",
 ]
 
+[[package]]
+name = "eonix_percpu"
+version = "0.1.0"
+dependencies = [
+ "eonix_percpu_macros",
+]
+
+[[package]]
+name = "eonix_percpu_macros"
+version = "0.1.0"
+dependencies = [
+ "arch_macros",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "eonix_preempt"
 version = "0.1.0"
 dependencies = [
- "arch",
+ "eonix_percpu",
 ]
 
 [[package]]
@@ -141,6 +166,7 @@ dependencies = [
  "arch",
  "atomic_unique_refcell",
  "eonix_log",
+ "eonix_percpu",
  "eonix_preempt",
  "eonix_sync",
  "intrusive-collections",
@@ -168,6 +194,7 @@ dependencies = [
  "buddy_allocator",
  "eonix_log",
  "eonix_mm",
+ "eonix_percpu",
  "eonix_preempt",
  "eonix_runtime",
  "eonix_sync",
@@ -259,15 +286,6 @@ dependencies = [
  "minimal-lexical",
 ]
 
-[[package]]
-name = "percpu-macros"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "pointers"
 version = "0.1.0"

+ 1 - 0
Cargo.toml

@@ -13,6 +13,7 @@ atomic_unique_refcell = { path = "./crates/atomic_unique_refcell", features = [
 ] }
 buddy_allocator = { path = "./crates/buddy_allocator" }
 eonix_mm = { path = "./crates/eonix_mm" }
+eonix_percpu = { path = "./crates/eonix_percpu" }
 eonix_preempt = { path = "./crates/eonix_preempt" }
 eonix_runtime = { path = "./crates/eonix_runtime" }
 eonix_sync = { path = "./crates/eonix_sync" }

+ 0 - 1
arch/Cargo.toml

@@ -5,5 +5,4 @@ edition = "2021"
 
 [dependencies]
 eonix_mm = { path = "../crates/eonix_mm" }
-percpu-macros = { path = "./percpu-macros" }
 cfg-if = "1.0"

+ 9 - 0
arch/arch_macros/Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "arch_macros"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+proc-macro2 = "1.0"
+quote = "1.0"
+syn = { version = "2.0", features = ["full"] }

+ 1 - 0
arch/arch_macros/src/lib.rs

@@ -0,0 +1 @@
+pub mod x86_64;

+ 1 - 0
arch/arch_macros/src/x86_64/mod.rs

@@ -0,0 +1 @@
+pub mod percpu;

+ 32 - 0
arch/arch_macros/src/x86_64/percpu.rs

@@ -0,0 +1,32 @@
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{Ident, LitStr, Type};
+
+/// Generate the assembly code to load the address of a symbol and add it to a register.
+pub fn load_addr_of_to(symbol: &LitStr, target: &LitStr) -> TokenStream {
+    quote! {
+        concat!("mov %gs:0, ", #target),
+        concat!("add $", #symbol, ", ", #target)
+    }
+}
+
+/// Get the base address for percpu variables of the current thread.
+pub fn get_percpu_pointer(percpu: &Ident, ty: &Type) -> TokenStream {
+    let stmt = load_addr_of_to(
+        &LitStr::new("{ident}", Span::call_site()),
+        &LitStr::new("{address}", Span::call_site()),
+    );
+
+    quote! {
+        {
+            let base: *mut #ty;
+            ::core::arch::asm!(
+                #stmt,
+                ident = sym #percpu,
+                address = out(reg) base,
+                options(att_syntax, nostack, preserves_flags)
+            );
+            base
+        }
+    }
+}

+ 0 - 47
arch/percpu-macros/Cargo.lock

@@ -1,47 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "percpu-macros"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.89"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"

+ 0 - 24
arch/percpu-macros/src/arch.rs

@@ -1,24 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::{Ident, Type};
-
-/// Get the base address for percpu variables of the current thread.
-pub fn get_percpu_pointer(percpu: &Ident, ty: &Type) -> TokenStream {
-    quote! {
-        {
-            #[cfg(target_arch = "x86_64")]
-            {
-                let base: *mut #ty;
-                ::core::arch::asm!(
-                    "mov %gs:0, {address}",
-                    "add ${percpu_pointer}, {address}",
-                    percpu_pointer = sym #percpu,
-                    address = out(reg) base,
-                    options(att_syntax)
-                );
-                base
-            }
-        }
-    }
-    .into()
-}

+ 2 - 1
arch/src/x86_64/mod.rs

@@ -6,6 +6,7 @@ mod interrupt;
 mod io;
 mod mm;
 mod percpu;
+// mod trap;
 mod user;
 
 use core::arch::asm;
@@ -21,7 +22,7 @@ pub use self::user::*;
 pub use fence::*;
 pub use mm::*;
 pub use percpu::*;
-pub use percpu_macros::{define_percpu, define_percpu_shared};
+// pub use trap::*;
 
 #[inline(always)]
 pub fn flush_tlb(vaddr: usize) {

+ 1 - 6
crates/eonix_percpu/Cargo.toml

@@ -3,10 +3,5 @@ name = "eonix_percpu"
 version = "0.1.0"
 edition = "2024"
 
-[lib]
-proc-macro = true
-
 [dependencies]
-proc-macro2 = "1.0"
-quote = "1.0"
-syn = { version = "2.0", features = ["full"] }
+eonix_percpu_macros = { path = "./eonix_percpu_macros" }

+ 3 - 1
arch/percpu-macros/Cargo.toml → crates/eonix_percpu/eonix_percpu_macros/Cargo.toml

@@ -1,5 +1,5 @@
 [package]
-name = "percpu-macros"
+name = "eonix_percpu_macros"
 version = "0.1.0"
 edition = "2021"
 
@@ -7,6 +7,8 @@ edition = "2021"
 proc-macro = true
 
 [dependencies]
+arch_macros = { path = "../../../arch/arch_macros" }
+
 proc-macro2 = "1.0"
 quote = "1.0"
 syn = { version = "2.0", features = ["full"] }

+ 41 - 12
arch/percpu-macros/src/lib.rs → crates/eonix_percpu/eonix_percpu_macros/src/lib.rs

@@ -1,18 +1,19 @@
 extern crate proc_macro;
 
-use proc_macro::TokenStream;
+use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
-use syn::{parse_macro_input, ItemStatic};
+use syn::{parse2, Ident, ItemStatic, Type};
 
-mod arch;
-
-#[proc_macro_attribute]
-pub fn define_percpu(attrs: TokenStream, item: TokenStream) -> TokenStream {
+fn define_percpu_impl(
+    attrs: TokenStream,
+    item: TokenStream,
+    get_percpu_pointer: fn(&Ident, &Type) -> TokenStream,
+) -> TokenStream {
     if !attrs.is_empty() {
         panic!("`define_percpu` attribute does not take any arguments");
     }
 
-    let item = parse_macro_input!(item as ItemStatic);
+    let item = parse2::<ItemStatic>(item).unwrap();
     let vis = &item.vis;
     let ident = &item.ident;
     let ty = &item.ty;
@@ -53,7 +54,7 @@ pub fn define_percpu(attrs: TokenStream, item: TokenStream) -> TokenStream {
         quote! {}
     };
 
-    let as_ptr = arch::get_percpu_pointer(&inner_ident, &ty);
+    let as_ptr = get_percpu_pointer(&inner_ident, &ty);
 
     quote! {
         #[link_section = ".percpu"]
@@ -116,13 +117,16 @@ pub fn define_percpu(attrs: TokenStream, item: TokenStream) -> TokenStream {
     .into()
 }
 
-#[proc_macro_attribute]
-pub fn define_percpu_shared(attrs: TokenStream, item: TokenStream) -> TokenStream {
+fn define_percpu_shared_impl(
+    attrs: TokenStream,
+    item: TokenStream,
+    get_percpu_pointer: fn(&Ident, &Type) -> TokenStream,
+) -> TokenStream {
     if !attrs.is_empty() {
         panic!("`define_percpu_shared` attribute does not take any arguments");
     }
 
-    let item = parse_macro_input!(item as ItemStatic);
+    let item = parse2::<ItemStatic>(item).unwrap();
     let vis = &item.vis;
     let ident = &item.ident;
     let ty = &item.ty;
@@ -131,7 +135,7 @@ pub fn define_percpu_shared(attrs: TokenStream, item: TokenStream) -> TokenStrea
     let inner_ident = format_ident!("_percpu_shared_inner_{}", ident);
     let access_ident = format_ident!("_access_shared_{}", ident);
 
-    let as_ptr = arch::get_percpu_pointer(&inner_ident, &ty);
+    let as_ptr = get_percpu_pointer(&inner_ident, &ty);
 
     quote! {
         #[link_section = ".percpu"]
@@ -177,5 +181,30 @@ pub fn define_percpu_shared(attrs: TokenStream, item: TokenStream) -> TokenStrea
             }
         }
     }
+}
+
+#[proc_macro_attribute]
+pub fn define_percpu_x86_64(
+    attrs: proc_macro::TokenStream,
+    item: proc_macro::TokenStream,
+) -> proc_macro::TokenStream {
+    define_percpu_impl(
+        attrs.into(),
+        item.into(),
+        arch_macros::x86_64::percpu::get_percpu_pointer,
+    )
+    .into()
+}
+
+#[proc_macro_attribute]
+pub fn define_percpu_shared_x86_64(
+    attrs: proc_macro::TokenStream,
+    item: proc_macro::TokenStream,
+) -> proc_macro::TokenStream {
+    define_percpu_shared_impl(
+        attrs.into(),
+        item.into(),
+        arch_macros::x86_64::percpu::get_percpu_pointer,
+    )
     .into()
 }

+ 0 - 24
crates/eonix_percpu/src/arch.rs

@@ -1,24 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::{Ident, Type};
-
-/// Get the base address for percpu variables of the current thread.
-pub fn get_percpu_pointer(percpu: &Ident, ty: &Type) -> TokenStream {
-    quote! {
-        {
-            #[cfg(target_arch = "x86_64")]
-            {
-                let base: *mut #ty;
-                ::core::arch::asm!(
-                    "mov %gs:0, {address}",
-                    "add ${percpu_pointer}, {address}",
-                    percpu_pointer = sym #percpu,
-                    address = out(reg) base,
-                    options(att_syntax)
-                );
-                base
-            }
-        }
-    }
-    .into()
-}

+ 5 - 179
crates/eonix_percpu/src/lib.rs

@@ -1,181 +1,7 @@
-extern crate proc_macro;
+#![no_std]
 
-use proc_macro::TokenStream;
-use quote::{format_ident, quote};
-use syn::{parse_macro_input, ItemStatic};
+#[cfg(target_arch = "x86_64")]
+pub use eonix_percpu_macros::define_percpu_x86_64 as define_percpu;
 
-mod arch;
-
-#[proc_macro_attribute]
-pub fn define_percpu(attrs: TokenStream, item: TokenStream) -> TokenStream {
-    if !attrs.is_empty() {
-        panic!("`define_percpu` attribute does not take any arguments");
-    }
-
-    let item = parse_macro_input!(item as ItemStatic);
-    let vis = &item.vis;
-    let ident = &item.ident;
-    let ty = &item.ty;
-    let expr = &item.expr;
-
-    let is_bool = quote!(#ty).to_string().as_str() == "bool";
-    let is_integer =
-        ["u8", "u16", "u32", "u64", "usize"].contains(&quote!(#ty).to_string().as_str());
-
-    let is_atomic_like = is_bool || is_integer || quote!(#ty).to_string().contains("NonNull");
-
-    let inner_ident = format_ident!("_percpu_inner_{}", ident);
-    let access_ident = format_ident!("_access_{}", ident);
-
-    let integer_methods = if is_integer {
-        quote! {
-            pub fn add(&self, value: #ty) {
-                *unsafe { self.as_mut() } += value;
-            }
-
-            pub fn sub(&self, value: #ty) {
-                *unsafe { self.as_mut() } -= value;
-            }
-        }
-    } else {
-        quote! {}
-    };
-
-    let preempt_disable = if !is_atomic_like {
-        quote! { eonix_preempt::disable(); }
-    } else {
-        quote! {}
-    };
-
-    let preempt_enable = if !is_atomic_like {
-        quote! { eonix_preempt::enable(); }
-    } else {
-        quote! {}
-    };
-
-    let as_ptr = arch::get_percpu_pointer(&inner_ident, &ty);
-
-    quote! {
-        #[link_section = ".percpu"]
-        #[allow(non_upper_case_globals)]
-        static mut #inner_ident: #ty = #expr;
-        #[allow(non_camel_case_types)]
-        #vis struct #access_ident;
-        #vis static #ident: #access_ident = #access_ident;
-
-        impl #access_ident {
-            /// # Safety
-            /// This function is unsafe because it allows for mutable aliasing of the percpu
-            /// variable.
-            /// Make sure that preempt is disabled when calling this function.
-            pub unsafe fn as_ptr(&self) -> *mut #ty {
-                #as_ptr
-            }
-
-            pub fn get(&self) -> #ty {
-                #preempt_disable
-                let value = unsafe { self.as_ptr().read() };
-                #preempt_enable
-                value
-            }
-
-            pub fn set(&self, value: #ty) {
-                #preempt_disable
-                unsafe { self.as_ptr().write(value) }
-                #preempt_enable
-            }
-
-            pub fn swap(&self, mut value: #ty) -> #ty {
-                #preempt_disable
-                unsafe { self.as_ptr().swap(&mut value) }
-                #preempt_enable
-                value
-            }
-
-            /// # Safety
-            /// This function is unsafe because it allows for immutable aliasing of the percpu
-            /// variable.
-            /// Make sure that preempt is disabled when calling this function.
-            pub unsafe fn as_ref(&self) -> & #ty {
-                // SAFETY: This is safe because `as_ptr()` is guaranteed to be valid.
-                self.as_ptr().as_ref().unwrap()
-            }
-
-            /// # Safety
-            /// This function is unsafe because it allows for mutable aliasing of the percpu
-            /// variable.
-            /// Make sure that preempt is disabled when calling this function.
-            pub unsafe fn as_mut(&self) -> &mut #ty {
-                // SAFETY: This is safe because `as_ptr()` is guaranteed to be valid.
-                self.as_ptr().as_mut().unwrap()
-            }
-
-            #integer_methods
-        }
-    }
-    .into()
-}
-
-#[proc_macro_attribute]
-pub fn define_percpu_shared(attrs: TokenStream, item: TokenStream) -> TokenStream {
-    if !attrs.is_empty() {
-        panic!("`define_percpu_shared` attribute does not take any arguments");
-    }
-
-    let item = parse_macro_input!(item as ItemStatic);
-    let vis = &item.vis;
-    let ident = &item.ident;
-    let ty = &item.ty;
-    let expr = &item.expr;
-
-    let inner_ident = format_ident!("_percpu_shared_inner_{}", ident);
-    let access_ident = format_ident!("_access_shared_{}", ident);
-
-    let as_ptr = arch::get_percpu_pointer(&inner_ident, &ty);
-
-    quote! {
-        #[link_section = ".percpu"]
-        #[allow(non_upper_case_globals)]
-        static #inner_ident: #ty = #expr;
-        #[allow(non_camel_case_types)]
-        #vis struct #access_ident;
-        #vis static #ident: #access_ident = #access_ident;
-
-        impl #access_ident {
-            fn as_ptr(&self) -> *const #ty {
-                unsafe { ( #as_ptr ) }
-            }
-
-            pub fn get_ref(&self) -> & #ty {
-                // SAFETY: This is safe because `as_ptr()` is guaranteed to be valid.
-                unsafe { self.as_ptr().as_ref().unwrap() }
-            }
-
-            pub fn get_for_cpu(&self, cpuid: usize) -> Option<& #ty > {
-                let offset = & #inner_ident as *const _ as usize;
-                let base = ::arch::PercpuArea::get_for(cpuid);
-                base.map(|base| unsafe { base.byte_add(offset).cast().as_ref() })
-            }
-        }
-
-        impl ::core::ops::Deref for #access_ident {
-            type Target = #ty;
-
-            fn deref(&self) -> &Self::Target {
-                self.get_ref()
-            }
-        }
-
-        impl<T> ::core::convert::AsRef<T> for #access_ident
-        where
-            <Self as ::core::ops::Deref>::Target: ::core::convert::AsRef<T>,
-        {
-            fn as_ref(&self) -> &T {
-                use ::core::ops::Deref;
-
-                self.deref().as_ref()
-            }
-        }
-    }
-    .into()
-}
+#[cfg(target_arch = "x86_64")]
+pub use eonix_percpu_macros::define_percpu_shared_x86_64 as define_percpu_shared;

+ 1 - 1
crates/eonix_preempt/Cargo.toml

@@ -4,4 +4,4 @@ version = "0.1.0"
 edition = "2024"
 
 [dependencies]
-arch = { path = "../../arch" }
+eonix_percpu = { path = "../eonix_percpu" }

+ 1 - 1
crates/eonix_preempt/src/lib.rs

@@ -2,7 +2,7 @@
 
 use core::sync::atomic::{compiler_fence, Ordering};
 
-#[arch::define_percpu]
+#[eonix_percpu::define_percpu]
 static PREEMPT_COUNT: usize = 0;
 
 #[inline(always)]

+ 1 - 0
crates/eonix_runtime/Cargo.toml

@@ -7,6 +7,7 @@ edition = "2024"
 arch = { path = "../../arch" }
 atomic_unique_refcell = { path = "../atomic_unique_refcell" }
 eonix_log = { path = "../eonix_log" }
+eonix_percpu = { path = "../eonix_percpu" }
 eonix_preempt = { path = "../eonix_preempt" }
 eonix_sync = { path = "../eonix_sync" }
 pointers = { path = "../pointers" }

+ 1 - 1
crates/eonix_runtime/src/ready_queue.rs

@@ -2,7 +2,7 @@ use crate::task::Task;
 use alloc::{collections::VecDeque, sync::Arc};
 use eonix_sync::Spin;
 
-#[arch::define_percpu_shared]
+#[eonix_percpu::define_percpu_shared]
 static READYQUEUE: Spin<FifoReadyQueue> = Spin::new(FifoReadyQueue::new());
 
 pub trait ReadyQueue {

+ 2 - 2
crates/eonix_runtime/src/scheduler.rs

@@ -18,10 +18,10 @@ use eonix_sync::{LazyLock, Spin, SpinIrq as _};
 use intrusive_collections::RBTree;
 use pointers::BorrowedArc;
 
-#[arch::define_percpu]
+#[eonix_percpu::define_percpu]
 static CURRENT_TASK: Option<NonNull<Task>> = None;
 
-#[arch::define_percpu]
+#[eonix_percpu::define_percpu]
 static LOCAL_SCHEDULER_CONTEXT: ExecutionContext = ExecutionContext::new();
 
 static TASKS: LazyLock<Spin<RBTree<TaskAdapter>>> =

+ 1 - 1
src/kernel/cpu.rs

@@ -4,7 +4,7 @@ use core::{alloc::Layout, pin::Pin, ptr::NonNull};
 use eonix_mm::paging::Page;
 use eonix_sync::LazyLock;
 
-#[arch::define_percpu]
+#[eonix_percpu::define_percpu]
 static CPU: LazyLock<CPU> = LazyLock::new(CPU::new);
 
 /// # Safety

+ 1 - 1
src/kernel/mem/page_alloc.rs

@@ -18,7 +18,7 @@ const BATCH_SIZE: u32 = 64;
 
 static BUDDY_ALLOC: Spin<BuddyAllocator<RawPagePtr>> = Spin::new(BuddyAllocator::new());
 
-#[arch::define_percpu]
+#[eonix_percpu::define_percpu]
 static PERCPU_PAGE_ALLOC: PerCpuPageAlloc = PerCpuPageAlloc::new();
 
 #[derive(Clone)]

+ 1 - 1
src/kernel/task/thread.rs

@@ -32,7 +32,7 @@ struct CurrentThread {
     runnable: NonNull<ThreadRunnable>,
 }
 
-#[arch::define_percpu]
+#[eonix_percpu::define_percpu]
 static CURRENT_THREAD: Option<CurrentThread> = None;
 
 pub struct ThreadBuilder {