xref: /kvm-unit-tests/lib/x86/apic.h (revision 7f528c1b474c0a743dbe277956064ce7599921ed)
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