1 #include <lwk/kernel.h>
3 #include <lwk/resource.h>
4 #include <lwk/bootmem.h>
5 #include <lwk/spinlock.h>
6 #include <lwk/cpuinfo.h>
8 #include <arch/pgtable.h>
9 #include <arch/fixmap.h>
10 #include <arch/apicdef.h>
11 #include <arch/io_apic.h>
12 #include <arch/idt_vectors.h>
15 * Lock that protects access to the IO APICs in the system.
16 * There is only one lock for all IO APICs.
18 static DEFINE_SPINLOCK(ioapic_lock);
21 * Number of IO APICs in the system.
23 unsigned int ioapic_num;
26 * Array containing the IDs of the IO APICs in the system.
27 * The array is indexed by ioapic_index.
29 unsigned int ioapic_id[MAX_IO_APICS] = { 1 };
32 * Addresses of the IO APICs in the system.
33 * The array is indexed by ioapic_index.
35 uintptr_t ioapic_phys_addr[MAX_IO_APICS] = { 0xFEC00000 };
38 * Resource entries for the IO APIC memory mapping.
40 static struct resource *ioapic_resources;
43 * Structure used to map IO APIC registers.
52 * Union used to map an IO APIC routing entry register.
54 union ioapic_entry_union {
55 struct { uint32_t low_word, high_word; };
56 struct IO_APIC_route_entry entry;
60 * Returns the base kernel virtual address of the specified IO APIC's
63 static struct ioapic *
64 ioapic_base_addr(int ioapic_index)
66 return (void *) __fix_to_virt(FIX_IO_APIC_BASE_0 + ioapic_index)
67 + (ioapic_phys_addr[ioapic_index] & ~PAGE_MASK);
71 * Reads a value from an IO APIC register.
74 ioapic_read(unsigned int ioapic_index, uint32_t reg)
76 struct ioapic *ioapic = ioapic_base_addr(ioapic_index);
77 writel(reg, &ioapic->index);
78 return readl(&ioapic->data);
82 * Writes a value to an IO APIC register.
85 ioapic_write(unsigned int ioapic_index, uint32_t reg, uint32_t value)
87 struct ioapic *ioapic = ioapic_base_addr(ioapic_index);
88 writel(reg, &ioapic->index);
89 writel(value, &ioapic->data);
93 * Reads an IO APIC pin routing entry.
95 static struct IO_APIC_route_entry
97 unsigned int ioapic_index,
101 union ioapic_entry_union eu;
104 spin_lock_irqsave(&ioapic_lock, flags);
105 eu.low_word = ioapic_read(ioapic_index, 0x10 + 2 * pin);
106 eu.high_word = ioapic_read(ioapic_index, 0x11 + 2 * pin);
107 spin_unlock_irqrestore(&ioapic_lock, flags);
113 * Writes an IO APIC pin routing entry.
115 * When we write a new IO APIC routing entry, we need to write the high word
116 * first. This is because the mask/enable bit is in the low word and we do not
117 * want to enable the entry before it is fully populated.
121 unsigned int ioapic_index,
123 struct IO_APIC_route_entry pin_config
126 union ioapic_entry_union eu;
129 spin_lock_irqsave(&ioapic_lock, flags);
130 eu.entry = pin_config;
131 ioapic_write(ioapic_index, 0x11 + 2 * pin, eu.high_word);
132 ioapic_write(ioapic_index, 0x10 + 2 * pin, eu.low_word);
133 spin_unlock_irqrestore(&ioapic_lock, flags);
137 * Masks (disables) an IO APIC input pin.
141 unsigned int ioapic_index,
145 struct IO_APIC_route_entry pin_config =
146 ioapic_read_pin(ioapic_index, pin);
148 ioapic_write_pin(ioapic_index, pin, pin_config);
152 * Unmasks (enables) an IO APIC input pin.
156 unsigned int ioapic_index,
160 struct IO_APIC_route_entry pin_config =
161 ioapic_read_pin(ioapic_index, pin);
163 ioapic_write_pin(ioapic_index, pin, pin_config);
167 * Returns the number of input pins provided by the specified IO APIC.
170 ioapic_get_num_pins(unsigned int ioapic_index)
172 union IO_APIC_reg_01 reg_01;
174 reg_01.raw = ioapic_read(ioapic_index, 1);
175 return reg_01.bits.entries + 1;
179 * Initializes the primary IO APIC (the one connected to the ISA IRQs).
183 unsigned int ioapic_index
187 unsigned int num_pins = ioapic_get_num_pins(ioapic_index);
188 struct IO_APIC_route_entry cfg;
191 panic("Expected IOAPIC to have 24 pins, has %u.", num_pins);
193 /* Mask (disable) all pins */
194 for (pin = 0; pin < num_pins; pin++) {
195 ioapic_mask_pin(ioapic_index, pin);
199 * Configure ISA IRQs.
200 * (Assuming pins [1,15] are the standard ISA IRQs)
201 * (Assuming pin 2 is hooked to the timer interrupt)
202 * (Assuming pin 0 is hooked to the old i8259 PIC... don't use it)
204 for (pin = 1; pin <= 15; pin++) {
205 cfg = ioapic_read_pin(ioapic_index, pin);
207 cfg.delivery_mode = ioapic_fixed;
208 cfg.dest_mode = ioapic_physical_dest;
209 cfg.polarity = (pin == 8)
211 : ioapic_active_high;
212 cfg.trigger = ioapic_edge_sensitive;
213 cfg.dest = (uint8_t) cpu_info[0].physical_id;
214 cfg.vector = IRQ0_VECTOR + pin;
216 ioapic_write_pin(ioapic_index, pin, cfg);
220 * Configure PCI IRQs.
221 * (Assuming pins [16,19] are PCI INTA, INTB, INTC, and INTD)
223 for (pin = 16; pin <= 19; pin++) {
224 cfg = ioapic_read_pin(ioapic_index, pin);
226 cfg.delivery_mode = ioapic_fixed;
227 cfg.dest_mode = ioapic_physical_dest;
228 cfg.polarity = ioapic_active_low;
229 cfg.trigger = ioapic_level_sensitive;
230 cfg.dest = (uint8_t) cpu_info[0].physical_id;
231 cfg.vector = IRQ0_VECTOR + pin;
233 ioapic_write_pin(ioapic_index, pin, cfg);
236 /* Unmask (enable) all of the pins that have been configured */
237 for (pin = 1; pin < 19; pin++) {
238 ioapic_unmask_pin(ioapic_index, pin);
243 * Creates a kernel mapping for all IO APICs in the system.
249 const int name_size = 16;
254 printk( "%s: Faking IO APIC\n", __func__ );
259 * Allocate enough memory for one resource structure per detected IO
260 * APIC in the system. Memory for the resource name strings is tacked
261 * onto the end of the allocation (name_size*ioapic_num bytes).
263 ioapic_resources = alloc_bootmem(ioapic_num *
264 (sizeof(struct resource) + name_size));
265 name = ((char *)ioapic_resources) + ioapic_num*sizeof(struct resource);
267 for (i = 0; i < ioapic_num; i++) {
268 /* Reserve the physical memory used by the IO APIC */
269 sprintf(name, "IO APIC %u", i);
270 ioapic_resources[i].name = name;
271 ioapic_resources[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
272 ioapic_resources[i].start = ioapic_phys_addr[i];
273 ioapic_resources[i].end = ioapic_phys_addr[i] + 4096 - 1;
274 request_resource(&iomem_resource, &ioapic_resources[i]);
277 /* Map the IO APIC into the kernel */
278 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + i, ioapic_phys_addr[i]);
281 "IO APIC mapped to virtual address 0x%016lx\n",
282 __fix_to_virt(FIX_IO_APIC_BASE_0 + i)
288 * Initializes all IO APICs in the system.
296 /* TODO: FIX THIS... NEED TO PARSE MPTABLE OR SOMETHING ELSE */
298 /* TODO: For now, only initializes the first one. */
299 ioapic_init_primary(0);
305 * Dumps the current state of all IO APICs in the system.
310 unsigned int ioapic_index, pin;
311 union IO_APIC_reg_00 reg_00;
312 union IO_APIC_reg_01 reg_01;
313 union IO_APIC_reg_02 reg_02;
314 struct IO_APIC_route_entry entry;
317 for (ioapic_index = 0; ioapic_index < ioapic_num; ioapic_index++) {
319 spin_lock_irqsave(&ioapic_lock, flags);
320 reg_00.raw = ioapic_read(ioapic_index, 0);
321 reg_01.raw = ioapic_read(ioapic_index, 1);
322 if (reg_01.bits.version >= 0x10)
323 reg_02.raw = ioapic_read(ioapic_index, 2);
324 spin_unlock_irqrestore(&ioapic_lock, flags);
326 printk(KERN_DEBUG "Dump of IO APIC %u (physical id %u):\n",
327 ioapic_index, ioapic_id[ioapic_index]);
328 printk(KERN_DEBUG " register #00: %08X\n", reg_00.raw);
329 printk(KERN_DEBUG " physical APIC id: %02u\n", reg_00.bits.ID);
330 printk(KERN_DEBUG " register #01: %08X\n", *(int *)®_01);
331 printk(KERN_DEBUG " max redirection entries: %04X\n", reg_01.bits.entries);
332 printk(KERN_DEBUG " PRQ implemented: %X\n", reg_01.bits.PRQ);
333 printk(KERN_DEBUG " IO APIC version: %04X\n", reg_01.bits.version);
334 if (reg_01.bits.version >= 0x10) {
335 printk(KERN_DEBUG " register #02: %08X\n", reg_02.raw);
336 printk(KERN_DEBUG " arbitration: %02X\n", reg_02.bits.arbitration);
339 printk(KERN_DEBUG " Interrupt Redirection Table:\n");
340 for (pin = 0; pin <= reg_01.bits.entries; pin++) {
341 entry = ioapic_read_pin(ioapic_index, pin);
343 " %02u: vector=%u dest=%03u mask=%1d "
344 "trigger=%1d irr=%1d polarity=%1d\n",
345 pin, entry.vector, entry.dest, entry.mask,
346 entry.trigger, entry.irr, entry.polarity);
348 " dest_mode=%1d delivery_mode=%1d "
349 "delivery_status=%1d\n",
350 entry.dest_mode, entry.delivery_mode,
351 entry.delivery_status);