λ

furix

cute os

settings

include/arch/x86_64/lapic.h

2054 bytes raw

#ifndef FURIX_ARCH_X86_64_LAPIC_H
#define FURIX_ARCH_X86_64_LAPIC_H

#include <types.h>

/* 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 */