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 })
}
}
#[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() -> !;
fn __secondary_start_kernel() -> !;
}
#[unsafe(export_name = "__ffi_start_kernel")]
#[doc(hidden)]
pub extern "C" fn ffi_start_kernel() {
unsafe {
__start_kernel();
}
}
#[unsafe(export_name = "__ffi_secondary_start_kernel")]
#[doc(hidden)]
pub extern "C" fn ffi_secondary_start_kernel() {
unsafe {
__secondary_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()
}