xref: /kvm-unit-tests/lib/x86/apic.h (revision 14432cc362f144c2210e52d1cc21bfa56db76c56)
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 /* Converts byte-addressable APIC register offset to 4-byte offset. */
63 static inline u32 apic_reg_index(u32 reg)
64 {
65 	return reg >> 2;
66 }
67 
68 static inline u32 x2apic_msr(u32 reg)
69 {
70 	return APIC_BASE_MSR + (reg >> 4);
71 }
72 
73 static inline bool apic_lvt_entry_supported(int idx)
74 {
75 	return GET_APIC_MAXLVT(apic_read(APIC_LVR)) >= idx;
76 }
77 
78 enum x2apic_reg_semantics {
79 	X2APIC_INVALID	= 0,
80 	X2APIC_READABLE	= BIT(0),
81 	X2APIC_WRITABLE	= BIT(1),
82 	X2APIC_RO	= X2APIC_READABLE,
83 	X2APIC_WO	= X2APIC_WRITABLE,
84 	X2APIC_RW	= X2APIC_READABLE | X2APIC_WRITABLE,
85 };
86 
87 static inline enum x2apic_reg_semantics get_x2apic_reg_semantics(u32 reg)
88 {
89 	assert(!(reg & 0xf));
90 
91 	switch (reg) {
92 	case APIC_ID:
93 	case APIC_LVR:
94 	case APIC_PROCPRI:
95 	case APIC_LDR:
96 	case APIC_ISR ... APIC_ISR + 0x70:
97 	case APIC_TMR ... APIC_TMR + 0x70:
98 	case APIC_IRR ... APIC_IRR + 0x70:
99 	case APIC_TMCCT:
100 		return X2APIC_RO;
101 	case APIC_TASKPRI:
102 	case APIC_SPIV:
103 	case APIC_ESR:
104 	case APIC_ICR:
105 	case APIC_LVTT:
106 	case APIC_LVTTHMR:
107 	case APIC_LVTPC:
108 	case APIC_LVT0:
109 	case APIC_LVT1:
110 	case APIC_LVTERR:
111 	case APIC_TMICT:
112 	case APIC_TDCR:
113 		return X2APIC_RW;
114 	case APIC_EOI:
115 	case APIC_SELF_IPI:
116 		return X2APIC_WO;
117 	case APIC_CMCI:
118 		if (apic_lvt_entry_supported(6))
119 			return X2APIC_RW;
120 		break;
121 	case APIC_RRR:
122 	case APIC_DFR:
123 	case APIC_ICR2:
124 	default:
125 		break;
126 	}
127 	return X2APIC_INVALID;
128 }
129 
130 #endif
131