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