1 #ifndef __ASM_IO_APIC_H
2 #define __ASM_IO_APIC_H
3
4 #include <asm/types.h>
5 #include <asm/mpspec.h>
6 #include <asm/apicdef.h>
7 #include <asm/fixmap.h>
8 #include <xen/iommu.h>
9
10 /*
11 * Intel IO-APIC support for SMP and UP systems.
12 *
13 * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
14 */
15
16 #define IO_APIC_BASE(idx) \
17 ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
18 + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK)))
19
20 #define IO_APIC_ID(idx) (mp_ioapics[idx].mpc_apicid)
21
22 /* I/O Unit Redirection Table */
23 #define IO_APIC_REDIR_VECTOR_MASK 0x000FF
24 #define IO_APIC_REDIR_DELIV_MODE_MASK 0x00700
25 #define IO_APIC_REDIR_DEST_LOGICAL 0x00800
26 #define IO_APIC_REDIR_DEST_PHYSICAL 0x00000
27 #define IO_APIC_REDIR_SEND_PENDING (1 << 12)
28 #define IO_APIC_REDIR_REMOTE_IRR (1 << 14)
29 #define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15)
30 #define IO_APIC_REDIR_MASKED (1 << 16)
31
32 /*
33 * The structure of the IO-APIC:
34 */
35 union IO_APIC_reg_00 {
36 uint32_t raw;
37 struct {
38 unsigned int __reserved_2:14;
39 unsigned int LTS:1;
40 unsigned int delivery_type:1;
41 unsigned int __reserved_1:8;
42 unsigned int ID:8;
43 } bits;
44 };
45
46 union IO_APIC_reg_01 {
47 uint32_t raw;
48 struct {
49 unsigned int version:8;
50 unsigned int __reserved_2:7;
51 unsigned int PRQ:1;
52 unsigned int entries:8;
53 unsigned int __reserved_1:8;
54 } bits;
55 };
56
57 union IO_APIC_reg_02 {
58 uint32_t raw;
59 struct {
60 unsigned int __reserved_2:24;
61 unsigned int arbitration:4;
62 unsigned int __reserved_1:4;
63 } bits;
64 };
65
66 union IO_APIC_reg_03 {
67 uint32_t raw;
68 struct {
69 unsigned int boot_DT:1;
70 unsigned int __reserved_1:31;
71 } bits;
72 };
73
74 /*
75 * # of IO-APICs and # of IRQ routing registers
76 */
77 extern int nr_ioapics;
78 extern int nr_ioapic_entries[MAX_IO_APICS];
79
80 enum ioapic_irq_destination_types {
81 dest_Fixed = 0,
82 dest_LowestPrio = 1,
83 dest_SMI = 2,
84 dest__reserved_1 = 3,
85 dest_NMI = 4,
86 dest_INIT = 5,
87 dest__reserved_2 = 6,
88 dest_ExtINT = 7
89 };
90
91 struct IO_APIC_route_entry {
92 unsigned int vector:8;
93 unsigned int delivery_mode:3; /*
94 * 000: FIXED
95 * 001: lowest prio
96 * 111: ExtINT
97 */
98 unsigned int dest_mode:1; /* 0: physical, 1: logical */
99 unsigned int delivery_status:1;
100 unsigned int polarity:1; /* 0: low, 1: high */
101 unsigned int irr:1;
102 unsigned int trigger:1; /* 0: edge, 1: level */
103 unsigned int mask:1; /* 0: enabled, 1: disabled */
104 unsigned int __reserved_2:15;
105
106 union {
107 struct {
108 unsigned int __reserved_1:24;
109 unsigned int physical_dest:4;
110 unsigned int __reserved_2:4;
111 } physical;
112
113 struct {
114 unsigned int __reserved_1:24;
115 unsigned int logical_dest:8;
116 } logical;
117
118 /* used when Interrupt Remapping with EIM is enabled */
119 unsigned int dest32;
120 } dest;
121 };
122
123 /*
124 * MP-BIOS irq configuration table structures:
125 */
126
127 /* I/O APIC entries */
128 extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
129
130 /* Base GSI for this IO APIC */
131 unsigned int io_apic_gsi_base(unsigned int apic);
132
133 /* Only need to remap ioapic RTE (reg: 10~3Fh) */
134 #define ioapic_reg_remapped(reg) (iommu_intremap && ((reg) >= 0x10))
135
__io_apic_read(unsigned int apic,unsigned int reg)136 static inline unsigned int __io_apic_read(unsigned int apic, unsigned int reg)
137 {
138 *IO_APIC_BASE(apic) = reg;
139 return *(IO_APIC_BASE(apic)+4);
140 }
141
io_apic_read(unsigned int apic,unsigned int reg)142 static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
143 {
144 if (ioapic_reg_remapped(reg))
145 return iommu_read_apic_from_ire(apic, reg);
146 return __io_apic_read(apic, reg);
147 }
148
__io_apic_write(unsigned int apic,unsigned int reg,unsigned int value)149 static inline void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
150 {
151 *IO_APIC_BASE(apic) = reg;
152 *(IO_APIC_BASE(apic)+4) = value;
153 }
154
io_apic_write(unsigned int apic,unsigned int reg,unsigned int value)155 static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
156 {
157 if (ioapic_reg_remapped(reg))
158 return iommu_update_ire_from_apic(apic, reg, value);
159 __io_apic_write(apic, reg, value);
160 }
161
162 /*
163 * Re-write a value: to be used for read-modify-write
164 * cycles where the read already set up the index register.
165 */
io_apic_modify(unsigned int apic,unsigned int reg,unsigned int value)166 static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
167 {
168 if (ioapic_reg_remapped(reg))
169 return iommu_update_ire_from_apic(apic, reg, value);
170 *(IO_APIC_BASE(apic)+4) = value;
171 }
172
173 /* 1 if "noapic" boot option passed */
174 extern bool skip_ioapic_setup;
175 extern bool ioapic_ack_new;
176 extern bool ioapic_ack_forced;
177
178 extern int io_apic_get_unique_id (int ioapic, int apic_id);
179 extern int io_apic_get_version (int ioapic);
180 extern int io_apic_get_redir_entries (int ioapic);
181 extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low);
182
183 extern void ioapic_init(void);
184
185 extern void ioapic_suspend(void);
186 extern void ioapic_resume(void);
187
188 extern void dump_ioapic_irq_info(void);
189
190 extern struct IO_APIC_route_entry __ioapic_read_entry(
191 unsigned int apic, unsigned int pin, bool raw);
192 void __ioapic_write_entry(
193 unsigned int apic, unsigned int pin, bool raw,
194 struct IO_APIC_route_entry);
195
196 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
197 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
198 extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
199 extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
200 extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries,
201 bool raw);
202
203 unsigned highest_gsi(void);
204
205 int ioapic_guest_read( unsigned long physbase, unsigned int reg, u32 *pval);
206 int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 pval);
207
208 #endif
209