#ifndef _X86_APIC_H_ #define _X86_APIC_H_ #include <bitops.h> #include <stdint.h> #include "apic-defs.h" #include "smp.h" extern u8 id_map[MAX_TEST_CPUS]; typedef struct { uint8_t vector; uint8_t delivery_mode:3; uint8_t dest_mode:1; uint8_t delivery_status:1; uint8_t polarity:1; uint8_t remote_irr:1; uint8_t trig_mode:1; uint8_t mask:1; uint8_t reserve:7; uint8_t reserved[4]; uint8_t dest_id; } ioapic_redir_entry_t; typedef enum trigger_mode { TRIGGER_EDGE = 0, TRIGGER_LEVEL, TRIGGER_MAX, } trigger_mode_t; void mask_pic_interrupts(void); void eoi(void); uint8_t apic_get_tpr(void); void apic_set_tpr(uint8_t tpr); void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e); void ioapic_write_reg(unsigned reg, uint32_t value); ioapic_redir_entry_t ioapic_read_redir(unsigned line); uint32_t ioapic_read_reg(unsigned reg); void ioapic_set_redir(unsigned line, unsigned vec, trigger_mode_t trig_mode); void set_mask(unsigned line, int mask); void set_irq_line(unsigned line, int val); void enable_apic(void); uint32_t apic_read(unsigned reg); bool apic_read_bit(unsigned reg, int n); void apic_write(unsigned reg, uint32_t val); void apic_icr_write(uint32_t val, uint32_t dest); uint32_t apic_id(void); uint32_t pre_boot_apic_id(void); int enable_x2apic(void); void disable_apic(void); void reset_apic(void); void init_apic_map(void); void apic_cleanup_timer(void); void apic_setup_timer(int vector, u32 mode); void apic_start_timer(u32 counter); void apic_stop_timer(void); /* Converts byte-addressable APIC register offset to 4-byte offset. */ static inline u32 apic_reg_index(u32 reg) { return reg >> 2; } static inline u32 x2apic_msr(u32 reg) { return APIC_BASE_MSR + (reg >> 4); } static inline bool apic_lvt_entry_supported(int idx) { return GET_APIC_MAXLVT(apic_read(APIC_LVR)) >= idx; } static inline u8 task_priority_class(u8 vector) { return vector >> 4; } enum x2apic_reg_semantics { X2APIC_INVALID = 0, X2APIC_READABLE = BIT(0), X2APIC_WRITABLE = BIT(1), X2APIC_RO = X2APIC_READABLE, X2APIC_WO = X2APIC_WRITABLE, X2APIC_RW = X2APIC_READABLE | X2APIC_WRITABLE, }; static inline enum x2apic_reg_semantics get_x2apic_reg_semantics(u32 reg) { assert(!(reg & 0xf)); switch (reg) { case APIC_ID: case APIC_LVR: case APIC_PROCPRI: case APIC_LDR: case APIC_ISR ... APIC_ISR + 0x70: case APIC_TMR ... APIC_TMR + 0x70: case APIC_IRR ... APIC_IRR + 0x70: case APIC_TMCCT: return X2APIC_RO; case APIC_TASKPRI: case APIC_SPIV: case APIC_ESR: case APIC_ICR: case APIC_LVTT: case APIC_LVTTHMR: case APIC_LVTPC: case APIC_LVT0: case APIC_LVT1: case APIC_LVTERR: case APIC_TMICT: case APIC_TDCR: return X2APIC_RW; case APIC_EOI: case APIC_SELF_IPI: return X2APIC_WO; case APIC_CMCI: if (apic_lvt_entry_supported(6)) return X2APIC_RW; break; case APIC_RRR: case APIC_DFR: case APIC_ICR2: default: break; } return X2APIC_INVALID; } #endif