semx_bsp_data 0.1.0

板级数据定义
//! 板级数据定义试试
//!
//! 板子的 bsp 定义, 包括 cpu 数量定义, 内存范围定义, 控制台定义, 中断控制器定义等.

use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{ItemStatic, Type, parse, parse_macro_input, token::Comma};

#[derive(Debug)]
struct BspDataArgs {
    console: Ident,
    irqchip: Ident,
}

impl parse::Parse for BspDataArgs {
    fn parse(input: parse::ParseStream) -> syn::Result<Self> {
        let console = input.parse()?;
        input.parse::<Comma>()?;
        let irqchip = input.parse()?;
        Ok(BspDataArgs { console, irqchip })
    }
}

/// 定义板级数据
///
/// # Panics
/// 当定义属性不符合`(console, irqchip)`时将会 panic.
#[proc_macro_attribute]
pub fn define_bsp_data(attr: TokenStream, input: TokenStream) -> TokenStream {
    let f = parse_macro_input!(input as ItemStatic);
    let at = parse_macro_input!(attr as BspDataArgs);
    let name = Ident::new(&format!("{}", f.ident), Span::call_site());

    let raw_ty = if let Type::Path(t) = f.ty.as_ref() {
        let ty2 = t.path.segments.first().unwrap().ident.clone();
        Some(Ident::new(&format!("{ty2}"), Span::call_site()))
    } else {
        None
    };
    let ty = raw_ty.unwrap();

    let console_ty = Ident::new(&format!("{}", at.console), Span::call_site());
    let irqchip_ty = Ident::new(&format!("{}", at.irqchip), Span::call_site());

    let asm0 = include_str!("aarch64/define.S");
    let asm1 = include_str!("aarch64/macro.S");
    let asm2 = include_str!("aarch64/head.S");
    let asm3 = include_str!("aarch64/cache.S");
    let asm4 = include_str!("aarch64/entry.S");
    let asm5 = include_str!("aarch64/clear_page.S");

    quote!(
        core::arch::global_asm!(#asm0);
        core::arch::global_asm!(#asm1);
        core::arch::global_asm!(#asm2);
        core::arch::global_asm!(#asm3);
        core::arch::global_asm!(#asm4);
        core::arch::global_asm!(#asm5);

        unsafe extern "Rust" {
            fn __start_kernel();
        }

        #[unsafe(export_name = "__ffi_start_kernel")]
        #[doc(hidden)]
        pub extern "C" fn ffi_start_kernel() {
            unsafe {
                __start_kernel();
            }
        }

        #[unsafe(export_name = "__early_init")]
        #[doc(hidden)]
        #[inline(always)]
        pub unsafe fn early_init() {
            #name.early_init();
        }

        #[unsafe(export_name = "__late_init")]
        #[doc(hidden)]
        #[inline(always)]
        pub unsafe fn late_init() {
            #name.late_init();
        }

        #[unsafe(export_name = "__secondary_init")]
        #[doc(hidden)]
        #[inline(always)]
        pub unsafe fn secondary_init() {
            #name.secondary_init();
        }

        #f

        static __SMP_DEFINE: seminix::bsp::smp::SmpDefine = #ty::DEFINE_SMP;
        #[unsafe(export_name = "__smp_define")]
        #[doc(hidden)]
        pub fn smp_define() -> &'static seminix::bsp::smp::SmpDefine {
            &__SMP_DEFINE
        }

        static __MEMS_DEFINE: seminix::bsp::memrange::MemDefine = #ty::DEFINE_MEMS;
        #[unsafe(export_name = "__mems_define")]
        #[doc(hidden)]
        pub fn mems_define() -> &'static seminix::bsp::memrange::MemDefine {
            &__MEMS_DEFINE
        }

        static __CONSOLE_DEFINE: seminix::sync::spinlock::Spinlock<#console_ty> =
                    seminix::sync::spinlock::Spinlock::new(#ty::DEFINE_CONSOLE);
        #[unsafe(export_name = "__console_init")]
        pub fn console_init() {
            let mut lock = __CONSOLE_DEFINE.lock_irq_save();
            use seminix::bsp::console::ConsoleImpl;
            lock.init();
        }
        #[unsafe(export_name = "__console_output")]
        #[doc(hidden)]
        pub fn console_output(args: core::fmt::Arguments<'_>) {
            let mut lock = __CONSOLE_DEFINE.lock_irq_save();
            use core::fmt::Write;
            lock.write_fmt(args).unwrap();
        }

        static __IRQ_MANAGE: seminix::irq::IrqManage<#irqchip_ty> =
                    seminix::irq::IrqManage::new(#ty::DEFINE_IRQCHIP);

        use seminix::bsp::irqchip::IrqchipImpl;
        #[unsafe(export_name = "__irqchip_name")]
        #[doc(hidden)]
        pub fn irqchip_name() -> &'static str {
            __IRQ_MANAGE.name()
        }

        #[unsafe(export_name = "__irq_disable")]
        #[doc(hidden)]
        pub fn irq_disable(hwirq: u32) {
            __IRQ_MANAGE.irq_disable(hwirq);
        }

        #[unsafe(export_name = "__irq_enable")]
        #[doc(hidden)]
        pub fn irq_enable(hwirq: u32) {
            __IRQ_MANAGE.irq_enable(hwirq);
        }

        #[unsafe(export_name = "__irq_set_type")]
        #[doc(hidden)]
        pub fn irq_set_type(hwirq: u32, irq_type: seminix::bsp::irqchip::IrqType) -> seminix::bsp::irqchip::Result<()> {
            __IRQ_MANAGE.irq_set_type(hwirq, irq_type)
        }

        #[unsafe(export_name = "__irq_set_affinity")]
        #[doc(hidden)]
        pub fn irq_set_affinity(hwirq: u32, cpumask: seminix::bsp::smp::Cpumask) -> seminix::bsp::irqchip::Result<()> {
            __IRQ_MANAGE.irq_set_affinity(hwirq, cpumask)
        }

        #[unsafe(export_name = "__irq_get_irqchip_state")]
        #[doc(hidden)]
        pub fn irq_get_irqchip_state(hwirq: u32, which: &seminix::bsp::irqchip::IrqchipIrqState) -> seminix::bsp::irqchip::Result<bool> {
            __IRQ_MANAGE.irq_get_irqchip_state(hwirq, which)
        }

        #[unsafe(export_name = "__irq_set_irqchip_state")]
        #[doc(hidden)]
        pub fn irq_set_irqchip_state(hwirq: u32, which: &seminix::bsp::irqchip::IrqchipIrqState, state: bool) -> seminix::bsp::irqchip::Result<()> {
            __IRQ_MANAGE.irq_set_irqchip_state(hwirq, which, state)
        }

        #[unsafe(export_name = "__send_ipi")]
        #[doc(hidden)]
        pub fn send_ipi(hwirq: u32, cpumask: &seminix::bsp::smp::Cpumask) {
            __IRQ_MANAGE.send_ipi(hwirq, cpumask);
        }

        #[unsafe(export_name = "__send_ipi_one")]
        #[doc(hidden)]
        pub fn send_ipi_one(hwirq: u32, cpu: usize) {
            __IRQ_MANAGE.send_ipi_one(hwirq, cpu);
        }

        #[unsafe(export_name = "__handle_irqchip_irq")]
        #[doc(hidden)]
        pub fn handle_irqchip_irq() {
            __IRQ_MANAGE.handle_irq();
        }

        #[unsafe(export_name = "__irq_init")]
        #[doc(hidden)]
        pub fn irq_init() {
            __IRQ_MANAGE.init();
        }

        #[unsafe(export_name = "__irq_init_cpu")]
        #[doc(hidden)]
        pub fn irq_init_cpu() {
            __IRQ_MANAGE.init_cpu();
        }
    )
    .into()
}