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
is_apic_hw_enabled(void)71 static inline bool is_apic_hw_enabled(void)
72 {
73 return rdmsr(MSR_IA32_APICBASE) & APIC_EN;
74 }
75
is_apic_sw_enabled(void)76 static inline bool is_apic_sw_enabled(void)
77 {
78 return apic_read(APIC_SPIV) & APIC_SPIV_APIC_ENABLED;
79 }
80
is_x2apic_enabled(void)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
is_xapic_enabled(void)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. */
apic_reg_index(u32 reg)92 static inline u32 apic_reg_index(u32 reg)
93 {
94 return reg >> 2;
95 }
96
x2apic_msr(u32 reg)97 static inline u32 x2apic_msr(u32 reg)
98 {
99 return APIC_BASE_MSR + (reg >> 4);
100 }
101
apic_lvt_entry_supported(int idx)102 static inline bool apic_lvt_entry_supported(int idx)
103 {
104 return GET_APIC_MAXLVT(apic_read(APIC_LVR)) >= idx;
105 }
106
task_priority_class(u8 vector)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
get_x2apic_reg_semantics(u32 reg)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