#ifndef FURIX_ARCH_X86_64_LAPIC_H #define FURIX_ARCH_X86_64_LAPIC_H #include /* delivery modes in ICR bits 8..10 */ #define LAPIC_IPI_FIXED 0x0 #define LAPIC_IPI_INIT 0x5 #define LAPIC_IPI_STARTUP 0x6 /* ICR shorthand in bits 18..19 */ #define LAPIC_DEST 0x0 #define LAPIC_SHORTHAND_SELF 0x1 #define LAPIC_SHORTHAND_ALL_EXCL 0x2 #define LAPIC_SHORTHAND_ALL 0x3 void lapic_enable(void); uint32_t lapic_base(void); uint32_t lapic_id(void); void lapic_eoi(void); /* wait until the last ICR write has been delivered (bounded) */ bool lapic_ipi_wait(void); /* * send an IPI and block until the LAPIC reports it delivered. synchronous by * design, for INIT/SIPI and the self-IPI test; a message-passing API belongs * on top of this rather than replacing it. */ uint32_t lapic_ipi_send(uint32_t delivery, uint32_t shorthand, uint32_t vector, uint32_t apic_id); /* * as lapic_ipi_send but with explicit ICR bits 13..15 (`flags`), used for the * INIT trigger bit that asserts and deasserts the reset level. * * every IPI entry point returns 0 on success and non-zero when the destination * ID is beyond what the xAPIC ICR can address. callers MUST check it: the * alternative is an INIT sent to processor 0, which resets the BSP. */ uint32_t lapic_ipi_send_flags(uint32_t delivery, uint32_t shorthand, uint32_t vector, uint32_t apic_id, uint32_t flags); /* * assert and deassert INIT for one processor. both halves are required: INIT is * level-triggered, so the assert (ICR bit 14) holds the target in reset and * only the deassert releases it to real mode at the reset vector, where it * waits for a SIPI. a deassert alone leaves the processor running wherever it * already was, so the SIPI has no held state to redirect. */ uint32_t lapic_ipi_init_assert(uint32_t apic_id); uint32_t lapic_ipi_init_deassert(uint32_t apic_id); /* startup-IPI, which releases a held processor at `vector << 12` */ uint32_t lapic_ipi_sipi(uint32_t apic_id, uint8_t vector); #endif /* FURIX_ARCH_X86_64_LAPIC_H */