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