2008-10-22 22:26:29 -07:00
|
|
|
#ifndef _ASM_X86_IO_APIC_H
|
|
|
|
#define _ASM_X86_IO_APIC_H
|
2008-01-30 05:30:37 -07:00
|
|
|
|
2008-04-19 07:55:13 -07:00
|
|
|
#include <linux/types.h>
|
2008-01-30 05:30:37 -07:00
|
|
|
#include <asm/mpspec.h>
|
|
|
|
#include <asm/apicdef.h>
|
2008-08-19 20:50:52 -07:00
|
|
|
#include <asm/irq_vectors.h>
|
2008-01-30 05:30:37 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Intel IO-APIC support for SMP and UP systems.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
|
|
|
|
*/
|
|
|
|
|
2008-06-07 08:53:56 -07:00
|
|
|
/* I/O Unit Redirection Table */
|
|
|
|
#define IO_APIC_REDIR_VECTOR_MASK 0x000FF
|
|
|
|
#define IO_APIC_REDIR_DEST_LOGICAL 0x00800
|
|
|
|
#define IO_APIC_REDIR_DEST_PHYSICAL 0x00000
|
|
|
|
#define IO_APIC_REDIR_SEND_PENDING (1 << 12)
|
|
|
|
#define IO_APIC_REDIR_REMOTE_IRR (1 << 14)
|
|
|
|
#define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15)
|
|
|
|
#define IO_APIC_REDIR_MASKED (1 << 16)
|
|
|
|
|
2008-01-30 05:30:37 -07:00
|
|
|
/*
|
|
|
|
* The structure of the IO-APIC:
|
|
|
|
*/
|
|
|
|
union IO_APIC_reg_00 {
|
|
|
|
u32 raw;
|
|
|
|
struct {
|
|
|
|
u32 __reserved_2 : 14,
|
|
|
|
LTS : 1,
|
|
|
|
delivery_type : 1,
|
|
|
|
__reserved_1 : 8,
|
|
|
|
ID : 8;
|
|
|
|
} __attribute__ ((packed)) bits;
|
|
|
|
};
|
|
|
|
|
|
|
|
union IO_APIC_reg_01 {
|
|
|
|
u32 raw;
|
|
|
|
struct {
|
|
|
|
u32 version : 8,
|
|
|
|
__reserved_2 : 7,
|
|
|
|
PRQ : 1,
|
|
|
|
entries : 8,
|
|
|
|
__reserved_1 : 8;
|
|
|
|
} __attribute__ ((packed)) bits;
|
|
|
|
};
|
|
|
|
|
|
|
|
union IO_APIC_reg_02 {
|
|
|
|
u32 raw;
|
|
|
|
struct {
|
|
|
|
u32 __reserved_2 : 24,
|
|
|
|
arbitration : 4,
|
|
|
|
__reserved_1 : 4;
|
|
|
|
} __attribute__ ((packed)) bits;
|
|
|
|
};
|
|
|
|
|
|
|
|
union IO_APIC_reg_03 {
|
|
|
|
u32 raw;
|
|
|
|
struct {
|
|
|
|
u32 boot_DT : 1,
|
|
|
|
__reserved_1 : 31;
|
|
|
|
} __attribute__ ((packed)) bits;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ioapic_irq_destination_types {
|
|
|
|
dest_Fixed = 0,
|
|
|
|
dest_LowestPrio = 1,
|
|
|
|
dest_SMI = 2,
|
|
|
|
dest__reserved_1 = 3,
|
|
|
|
dest_NMI = 4,
|
|
|
|
dest_INIT = 5,
|
|
|
|
dest__reserved_2 = 6,
|
|
|
|
dest_ExtINT = 7
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IO_APIC_route_entry {
|
|
|
|
__u32 vector : 8,
|
|
|
|
delivery_mode : 3, /* 000: FIXED
|
|
|
|
* 001: lowest prio
|
|
|
|
* 111: ExtINT
|
|
|
|
*/
|
|
|
|
dest_mode : 1, /* 0: physical, 1: logical */
|
|
|
|
delivery_status : 1,
|
|
|
|
polarity : 1,
|
|
|
|
irr : 1,
|
|
|
|
trigger : 1, /* 0: edge, 1: level */
|
|
|
|
mask : 1, /* 0: enabled, 1: disabled */
|
|
|
|
__reserved_2 : 15;
|
|
|
|
|
|
|
|
__u32 __reserved_3 : 24,
|
|
|
|
dest : 8;
|
|
|
|
} __attribute__ ((packed));
|
|
|
|
|
x64, x2apic/intr-remap: IO-APIC support for interrupt-remapping
IO-APIC support in the presence of interrupt-remapping infrastructure.
IO-APIC RTE will be programmed with interrupt-remapping table entry(IRTE)
index and the IRTE will contain information about the vector, cpu destination,
trigger mode etc, which traditionally was present in the IO-APIC RTE.
Introduce a new irq_chip for cleaner irq migration (in the process
context as opposed to the current irq migration in the context of an interrupt.
interrupt-remapping infrastructure will help us achieve this cleanly).
For edge triggered, irq migration is a simple atomic update(of vector
and cpu destination) of IRTE and flush the hardware cache.
For level triggered, we need to modify the io-apic RTE aswell with the update
vector information, along with modifying IRTE with vector and cpu destination.
So irq migration for level triggered is little bit more complex compared to
edge triggered migration. But the good news is, we use the same algorithm
for level triggered migration as we have today, only difference being,
we now initiate the irq migration from process context instead of the
interrupt context.
In future, when we do a directed EOI (combined with cpu EOI broadcast
suppression) to the IO-APIC, level triggered irq migration will also be
as simple as edge triggered migration and we can do the irq migration
with a simple atomic update to IO-APIC RTE.
TBD: some tests/changes needed in the presence of fixup_irqs() for
level triggered irq migration.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: akpm@linux-foundation.org
Cc: arjan@linux.intel.com
Cc: andi@firstfloor.org
Cc: ebiederm@xmission.com
Cc: jbarnes@virtuousgeek.org
Cc: steiner@sgi.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2008-07-10 11:16:56 -07:00
|
|
|
struct IR_IO_APIC_route_entry {
|
|
|
|
__u64 vector : 8,
|
|
|
|
zero : 3,
|
|
|
|
index2 : 1,
|
|
|
|
delivery_status : 1,
|
|
|
|
polarity : 1,
|
|
|
|
irr : 1,
|
|
|
|
trigger : 1,
|
|
|
|
mask : 1,
|
|
|
|
reserved : 31,
|
|
|
|
format : 1,
|
|
|
|
index : 15;
|
2008-01-30 05:30:37 -07:00
|
|
|
} __attribute__ ((packed));
|
|
|
|
|
|
|
|
#ifdef CONFIG_X86_IO_APIC
|
|
|
|
|
|
|
|
/*
|
|
|
|
* # of IO-APICs and # of IRQ routing registers
|
|
|
|
*/
|
|
|
|
extern int nr_ioapics;
|
|
|
|
extern int nr_ioapic_registers[MAX_IO_APICS];
|
|
|
|
|
2008-04-19 07:55:13 -07:00
|
|
|
#define MP_MAX_IOAPIC_PIN 127
|
|
|
|
|
2008-01-30 05:30:37 -07:00
|
|
|
/* I/O APIC entries */
|
2009-01-12 05:16:17 -07:00
|
|
|
extern struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
|
2008-01-30 05:30:37 -07:00
|
|
|
|
|
|
|
/* # of MP IRQ source entries */
|
|
|
|
extern int mp_irq_entries;
|
|
|
|
|
|
|
|
/* MP IRQ source entries */
|
2009-01-12 05:17:22 -07:00
|
|
|
extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
|
2008-01-30 05:30:37 -07:00
|
|
|
|
|
|
|
/* non-0 if default (table-less) MP configuration */
|
|
|
|
extern int mpc_default_type;
|
|
|
|
|
|
|
|
/* Older SiS APIC requires we rewrite the index register */
|
|
|
|
extern int sis_apic_bug;
|
|
|
|
|
|
|
|
/* 1 if "noapic" boot option passed */
|
|
|
|
extern int skip_ioapic_setup;
|
|
|
|
|
2008-06-11 07:35:14 -07:00
|
|
|
/* 1 if "noapic" boot option passed */
|
|
|
|
extern int noioapicquirk;
|
|
|
|
|
2008-06-11 07:35:15 -07:00
|
|
|
/* -1 if "noapic" boot option passed */
|
|
|
|
extern int noioapicreroute;
|
|
|
|
|
2008-05-21 14:10:22 -07:00
|
|
|
/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
|
|
|
|
extern int timer_through_8259;
|
|
|
|
|
2008-01-30 05:30:37 -07:00
|
|
|
/*
|
|
|
|
* If we use the IO-APIC for IRQ routing, disable automatic
|
|
|
|
* assignment of PCI IRQ's.
|
|
|
|
*/
|
|
|
|
#define io_apic_assign_pci_irqs \
|
|
|
|
(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
|
|
|
|
|
2009-07-07 20:01:15 -07:00
|
|
|
extern u8 io_apic_unique_id(u8 id);
|
2008-01-30 05:30:37 -07:00
|
|
|
extern int io_apic_get_unique_id(int ioapic, int apic_id);
|
|
|
|
extern int io_apic_get_version(int ioapic);
|
|
|
|
extern int io_apic_get_redir_entries(int ioapic);
|
|
|
|
|
2009-05-15 13:05:16 -07:00
|
|
|
struct io_apic_irq_attr;
|
|
|
|
extern int io_apic_set_pci_routing(struct device *dev, int irq,
|
|
|
|
struct io_apic_irq_attr *irq_attr);
|
2010-02-10 02:20:05 -07:00
|
|
|
void setup_IO_APIC_irq_extra(u32 gsi);
|
2008-01-30 05:30:37 -07:00
|
|
|
extern void ioapic_init_mappings(void);
|
2009-07-10 09:36:20 -07:00
|
|
|
extern void ioapic_insert_resources(void);
|
2008-01-30 05:30:37 -07:00
|
|
|
|
2009-03-27 14:22:44 -07:00
|
|
|
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
|
|
|
|
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
|
|
|
|
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
|
|
|
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
|
|
|
extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
2008-07-10 11:16:47 -07:00
|
|
|
|
2008-12-05 19:58:33 -07:00
|
|
|
extern void probe_nr_irqs_gsi(void);
|
2008-08-19 20:50:52 -07:00
|
|
|
|
2009-02-09 13:05:47 -07:00
|
|
|
extern int setup_ioapic_entry(int apic, int irq,
|
|
|
|
struct IO_APIC_route_entry *entry,
|
|
|
|
unsigned int destination, int trigger,
|
x86, x2apic: cleanup the IO-APIC level migration with interrupt-remapping
Impact: simplification
In the current code, for level triggered migration, we need to modify the
io-apic RTE with the update vector information, along with modifying interrupt
remapping table entry(IRTE) with vector and destination. This is to ensure that
remote IRR bit inthe IOAPIC RTE gets cleared when the cpu does EOI.
With this patch, for level triggered, we eliminate the io-apic RTE modification
(with the updated vector information), by using a virtual vector (io-apic pin
number). Real vector that is used for interrupting cpu will be coming from
the interrupt-remapping table entry. Trigger mode in the IRTE will always be
edge, and the actual level or edge trigger will be setup in the IO-APIC RTE.
So a level triggered interrupt will appear as an edge to the local apic
cpu but still as level to the IO-APIC.
With this change, level irq migration can be done by simply modifying
the interrupt-remapping table entry with out changing the io-apic RTE.
And as the interrupt appears as edge at the cpu, in addition to do the
local apic EOI, we need to do IO-APIC directed EOI to clear the remote
IRR bit in the IO-APIC RTE.
This simplies the irq migration in the presence of interrupt-remapping.
Idea-by: Rajesh Sankaran <rajesh.sankaran@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
2009-03-16 17:05:01 -07:00
|
|
|
int polarity, int vector, int pin);
|
2009-02-09 13:05:47 -07:00
|
|
|
extern void ioapic_write_entry(int apic, int pin,
|
|
|
|
struct IO_APIC_route_entry e);
|
2009-08-20 00:27:29 -07:00
|
|
|
extern void setup_ioapic_ids_from_mpc(void);
|
2009-07-07 20:01:15 -07:00
|
|
|
|
|
|
|
struct mp_ioapic_gsi{
|
2010-03-30 01:07:09 -07:00
|
|
|
u32 gsi_base;
|
|
|
|
u32 gsi_end;
|
2009-07-07 20:01:15 -07:00
|
|
|
};
|
|
|
|
extern struct mp_ioapic_gsi mp_gsi_routing[];
|
2010-06-08 11:44:32 -07:00
|
|
|
extern u32 gsi_top;
|
2010-03-30 01:07:09 -07:00
|
|
|
int mp_find_ioapic(u32 gsi);
|
|
|
|
int mp_find_ioapic_pin(int ioapic, u32 gsi);
|
2009-07-07 20:01:15 -07:00
|
|
|
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
|
2009-09-23 07:20:23 -07:00
|
|
|
extern void __init pre_init_apic_IRQ0(void);
|
2009-07-07 20:01:15 -07:00
|
|
|
|
2008-01-30 05:30:37 -07:00
|
|
|
#else /* !CONFIG_X86_IO_APIC */
|
2009-09-18 14:05:47 -07:00
|
|
|
|
2008-01-30 05:30:37 -07:00
|
|
|
#define io_apic_assign_pci_irqs 0
|
2009-08-20 00:27:29 -07:00
|
|
|
#define setup_ioapic_ids_from_mpc x86_init_noop
|
2008-05-21 14:10:22 -07:00
|
|
|
static const int timer_through_8259 = 0;
|
2008-12-08 10:47:51 -07:00
|
|
|
static inline void ioapic_init_mappings(void) { }
|
2009-07-10 09:36:20 -07:00
|
|
|
static inline void ioapic_insert_resources(void) { }
|
2008-12-08 10:47:51 -07:00
|
|
|
static inline void probe_nr_irqs_gsi(void) { }
|
2010-06-08 11:44:32 -07:00
|
|
|
#define gsi_top (NR_IRQS_LEGACY)
|
2010-03-30 01:07:09 -07:00
|
|
|
static inline int mp_find_ioapic(u32 gsi) { return 0; }
|
2009-09-18 14:05:47 -07:00
|
|
|
|
2010-02-23 11:43:58 -07:00
|
|
|
struct io_apic_irq_attr;
|
|
|
|
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
|
|
|
|
struct io_apic_irq_attr *irq_attr) { return 0; }
|
2007-10-11 02:20:03 -07:00
|
|
|
#endif
|
2008-01-30 05:30:37 -07:00
|
|
|
|
2008-10-22 22:26:29 -07:00
|
|
|
#endif /* _ASM_X86_IO_APIC_H */
|