1 #ifndef _X86_APIC_H_ 2 #define _X86_APIC_H_ 3 4 #include <bitops.h> 5 #include <stdint.h> 6 7 #include "apic-defs.h" 8 #include "processor.h" 9 #include "smp.h" 10 11 extern u8 id_map[MAX_TEST_CPUS]; 12 13 typedef struct { 14 uint8_t vector; 15 uint8_t delivery_mode:3; 16 uint8_t dest_mode:1; 17 uint8_t delivery_status:1; 18 uint8_t polarity:1; 19 uint8_t remote_irr:1; 20 uint8_t trig_mode:1; 21 uint8_t mask:1; 22 uint8_t reserve:7; 23 uint8_t reserved[4]; 24 uint8_t dest_id; 25 } ioapic_redir_entry_t; 26 27 typedef enum trigger_mode { 28 TRIGGER_EDGE = 0, 29 TRIGGER_LEVEL, 30 TRIGGER_MAX, 31 } trigger_mode_t; 32 33 void mask_pic_interrupts(void); 34 35 void eoi(void); 36 uint8_t apic_get_tpr(void); 37 void apic_set_tpr(uint8_t tpr); 38 39 void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e); 40 void ioapic_write_reg(unsigned reg, uint32_t value); 41 ioapic_redir_entry_t ioapic_read_redir(unsigned line); 42 uint32_t ioapic_read_reg(unsigned reg); 43 44 void ioapic_set_redir(unsigned line, unsigned vec, 45 trigger_mode_t trig_mode); 46 47 void set_mask(unsigned line, int mask); 48 49 void set_irq_line(unsigned line, int val); 50 51 void enable_apic(void); 52 uint32_t apic_read(unsigned reg); 53 bool apic_read_bit(unsigned reg, int n); 54 void apic_write(unsigned reg, uint32_t val); 55 void apic_icr_write(uint32_t val, uint32_t dest); 56 uint32_t apic_id(void); 57 uint32_t pre_boot_apic_id(void); 58 59 60 int enable_x2apic(void); 61 void disable_apic(void); 62 void reset_apic(void); 63 void init_apic_map(void); 64 65 void apic_cleanup_timer(void); 66 void apic_setup_timer(int vector, u32 mode); 67 68 void apic_start_timer(u32 counter); 69 void apic_stop_timer(void); 70 71 static inline bool is_apic_hw_enabled(void) 72 { 73 return rdmsr(MSR_IA32_APICBASE) & APIC_EN; 74 } 75 76 static inline bool is_apic_sw_enabled(void) 77 { 78 return apic_read(APIC_SPIV) & APIC_SPIV_APIC_ENABLED; 79 } 80 81 static inline bool is_x2apic_enabled(void) 82 { 83 return (rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == (APIC_EN | APIC_EXTD); 84 } 85 86 static inline bool is_xapic_enabled(void) 87 { 88 return (rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN; 89 } 90 91 /* Converts byte-addressable APIC register offset to 4-byte offset. */ 92 static inline u32 apic_reg_index(u32 reg) 93 { 94 return reg >> 2; 95 } 96 97 static inline u32 x2apic_msr(u32 reg) 98 { 99 return APIC_BASE_MSR + (reg >> 4); 100 } 101 102 static inline bool apic_lvt_entry_supported(int idx) 103 { 104 return GET_APIC_MAXLVT(apic_read(APIC_LVR)) >= idx; 105 } 106 107 static inline u8 task_priority_class(u8 vector) 108 { 109 return vector >> 4; 110 } 111 112 enum x2apic_reg_semantics { 113 X2APIC_INVALID = 0, 114 X2APIC_READABLE = BIT(0), 115 X2APIC_WRITABLE = BIT(1), 116 X2APIC_RO = X2APIC_READABLE, 117 X2APIC_WO = X2APIC_WRITABLE, 118 X2APIC_RW = X2APIC_READABLE | X2APIC_WRITABLE, 119 }; 120 121 static inline enum x2apic_reg_semantics get_x2apic_reg_semantics(u32 reg) 122 { 123 assert(!(reg & 0xf)); 124 125 switch (reg) { 126 case APIC_ID: 127 case APIC_LVR: 128 case APIC_PROCPRI: 129 case APIC_LDR: 130 case APIC_ISR ... APIC_ISR + 0x70: 131 case APIC_TMR ... APIC_TMR + 0x70: 132 case APIC_IRR ... APIC_IRR + 0x70: 133 case APIC_TMCCT: 134 return X2APIC_RO; 135 case APIC_TASKPRI: 136 case APIC_SPIV: 137 case APIC_ESR: 138 case APIC_ICR: 139 case APIC_LVTT: 140 case APIC_LVTTHMR: 141 case APIC_LVTPC: 142 case APIC_LVT0: 143 case APIC_LVT1: 144 case APIC_LVTERR: 145 case APIC_TMICT: 146 case APIC_TDCR: 147 return X2APIC_RW; 148 case APIC_EOI: 149 case APIC_SELF_IPI: 150 return X2APIC_WO; 151 case APIC_CMCI: 152 if (apic_lvt_entry_supported(6)) 153 return X2APIC_RW; 154 break; 155 case APIC_RRR: 156 case APIC_DFR: 157 case APIC_ICR2: 158 default: 159 break; 160 } 161 return X2APIC_INVALID; 162 } 163 164 #endif 165