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,
clock: 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()?;
input.parse::<Comma>()?;
let clock = input.parse()?;
Ok(BspDataArgs { console, irqchip, clock })
}
}
#[allow(clippy::too_many_lines)]
#[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 clock_ty = Ident::new(&format!("{}", at.clock), Span::call_site());
let asm0 = include_str!(concat!(env!("OUT_DIR"), "/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 __IRQCHIP: #irqchip_ty = #ty::DEFINE_IRQCHIP;
use seminix::bsp::irqchip::IrqchipImpl;
#[unsafe(export_name = "__irqchip_name")]
#[doc(hidden)]
pub fn irqchip_name() -> &'static str {
<#irqchip_ty as IrqchipImpl>::NAME
}
#[unsafe(export_name = "__irqchip_irqs_max")]
#[doc(hidden)]
pub fn irqchip_irqs_max() -> usize {
<#irqchip_ty as IrqchipImpl>::IRQS_MAX
}
#[unsafe(export_name = "__irqchip_irq_ack")]
#[doc(hidden)]
pub fn irqchip_irq_ack(hwirq: u32) {
__IRQCHIP.irq_ack(hwirq)
}
#[unsafe(export_name = "__irqchip_irq_eoi")]
#[doc(hidden)]
pub fn irqchip_irq_eoi(hwirq: u32) {
__IRQCHIP.irq_eoi(hwirq)
}
#[unsafe(export_name = "__irqchip_irq_disable")]
#[doc(hidden)]
pub fn irqchip_irq_disable(hwirq: u32) {
__IRQCHIP.irq_disable(hwirq);
}
#[unsafe(export_name = "__irqchip_irq_enable")]
#[doc(hidden)]
pub fn irqchip_irq_enable(hwirq: u32) {
__IRQCHIP.irq_enable(hwirq);
}
#[unsafe(export_name = "__irqchip_irq_set_affinity")]
#[doc(hidden)]
pub fn irqchip_irq_set_affinity(hwirq: u32, cpumask: &semx_cpumask::Cpumask) -> seminix::bsp::irqchip::Result<()> {
__IRQCHIP.irq_set_affinity(hwirq, cpumask)
}
#[unsafe(export_name = "__irqchip_irq_set_type")]
#[doc(hidden)]
pub fn irqchip_irq_set_type(hwirq: u32, irq_type: seminix::bsp::irqchip::IrqType) -> seminix::bsp::irqchip::Result<()> {
__IRQCHIP.irq_set_type(hwirq, irq_type)
}
#[unsafe(export_name = "__irqchip_irq_get_irqchip_state")]
#[doc(hidden)]
pub fn irqchip_irq_get_irqchip_state(hwirq: u32, which: seminix::bsp::irqchip::IrqchipIrqState) -> seminix::bsp::irqchip::Result<bool> {
__IRQCHIP.irq_get_irqchip_state(hwirq, which)
}
#[unsafe(export_name = "__irqchip_irq_set_irqchip_state")]
#[doc(hidden)]
pub fn irqchip_irq_set_irqchip_state(hwirq: u32, which: seminix::bsp::irqchip::IrqchipIrqState, state: bool) -> seminix::bsp::irqchip::Result<()> {
__IRQCHIP.irq_set_irqchip_state(hwirq, which, state)
}
#[unsafe(export_name = "__irqchip_ipi_send_single")]
#[doc(hidden)]
pub fn irqchip_ipi_send_single(hwirq: u32, cpu: usize) {
__IRQCHIP.ipi_send_single(hwirq, cpu);
}
#[unsafe(export_name = "__irqchip_ipi_send_mask")]
#[doc(hidden)]
pub fn irqchip_ipi_send_mask(hwirq: u32, cpumask: &semx_cpumask::Cpumask) {
__IRQCHIP.ipi_send_mask(hwirq, cpumask);
}
#[unsafe(export_name = "__irqchip_irq_handler")]
#[doc(hidden)]
pub fn irqchip_irq_handler() {
__IRQCHIP.irq_handler();
}
#[unsafe(export_name = "__irqchip_irq_init")]
#[doc(hidden)]
pub fn irqchip_irq_init() {
__IRQCHIP.irq_init();
}
#[unsafe(export_name = "__irqchip_irq_init_cpu")]
#[doc(hidden)]
pub fn irqchip_irq_init_cpu() {
__IRQCHIP.irq_init_cpu();
}
static __CLOCK_DEFINE: #clock_ty = #ty::DEFINE_CLOCK;
use seminix::bsp::clocksource::ClockImpl;
#[unsafe(export_name = "__clock_init")]
#[doc(hidden)]
pub fn clock_init() {
__CLOCK_DEFINE.init()
}
#[unsafe(export_name = "__clock_init_cpu")]
#[doc(hidden)]
pub fn clock_init_cpu() {
__CLOCK_DEFINE.init_cpu()
}
#[unsafe(export_name = "__clock_get_set_next_event")]
#[doc(hidden)]
pub fn get_set_next_event() -> seminix::bsp::clocksource::SetNextEventFunc {
__CLOCK_DEFINE.get_set_next_event()
}
#[unsafe(export_name = "__clock_get_set_state_stopped")]
#[doc(hidden)]
pub fn get_set_state_stopped() -> seminix::bsp::clocksource::SetStateStoppedFunc {
__CLOCK_DEFINE.get_set_state_stopped()
}
#[unsafe(export_name = "__clock_rate")]
#[doc(hidden)]
pub fn rate() -> usize {
__CLOCK_DEFINE.rate()
}
#[unsafe(export_name = "__clock_min_delta")]
#[doc(hidden)]
pub fn min_delta() -> u64 {
__CLOCK_DEFINE.min_delta()
}
#[unsafe(export_name = "__clock_max_delta")]
#[doc(hidden)]
pub fn max_delta() -> u64 {
__CLOCK_DEFINE.max_delta()
}
)
.into()
}