![Eric W. Biederman](/assets/img/avatar_default.png)
When I introduced the global variable gsi_end I thought gsi_end on io_apics was one past the end of the gsi range for the io_apic. After it was pointed out the the range on io_apics was inclusive I changed my global variable to match. That was a big mistake. Inclusive semantics without a range start cannot describe the case when no gsi's are allocated. Describing the case where no gsi's are allocated is important in sfi.c and mpparse.c so that we can assign gsi numbers instead of blindly copying the gsi assignments the BIOS has done as we do in the acpi case. To keep from getting the global variable confused with the gsi range end rename it gsi_top. To allow describing the case where no gsi's are allocated have gsi_top be one place the highest gsi number seen in the system. This fixes an off by one bug in sfi.c: Reported-by: jacob pan <jacob.jun.pan@linux.intel.com> This fixes the same off by one bug in mpparse.c: This fixes an off unreachable by one bug in acpi/boot.c:irq_to_gsi Reported-by: Yinghai <yinghai.lu@oracle.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> LKML-Reference: <m17hm9jre7.fsf_-_@fess.ebiederm.org> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
209 lines
5.1 KiB
C
209 lines
5.1 KiB
C
#ifndef _ASM_X86_IO_APIC_H
|
|
#define _ASM_X86_IO_APIC_H
|
|
|
|
#include <linux/types.h>
|
|
#include <asm/mpspec.h>
|
|
#include <asm/apicdef.h>
|
|
#include <asm/irq_vectors.h>
|
|
|
|
/*
|
|
* Intel IO-APIC support for SMP and UP systems.
|
|
*
|
|
* Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
|
|
*/
|
|
|
|
/* 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)
|
|
|
|
/*
|
|
* 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));
|
|
|
|
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;
|
|
} __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];
|
|
|
|
#define MP_MAX_IOAPIC_PIN 127
|
|
|
|
/* I/O APIC entries */
|
|
extern struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
|
|
|
|
/* # of MP IRQ source entries */
|
|
extern int mp_irq_entries;
|
|
|
|
/* MP IRQ source entries */
|
|
extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
|
|
|
|
/* 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;
|
|
|
|
/* 1 if "noapic" boot option passed */
|
|
extern int noioapicquirk;
|
|
|
|
/* -1 if "noapic" boot option passed */
|
|
extern int noioapicreroute;
|
|
|
|
/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
|
|
extern int timer_through_8259;
|
|
|
|
/*
|
|
* 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)
|
|
|
|
extern u8 io_apic_unique_id(u8 id);
|
|
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);
|
|
|
|
struct io_apic_irq_attr;
|
|
extern int io_apic_set_pci_routing(struct device *dev, int irq,
|
|
struct io_apic_irq_attr *irq_attr);
|
|
void setup_IO_APIC_irq_extra(u32 gsi);
|
|
extern void ioapic_init_mappings(void);
|
|
extern void ioapic_insert_resources(void);
|
|
|
|
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);
|
|
|
|
extern void probe_nr_irqs_gsi(void);
|
|
|
|
extern int setup_ioapic_entry(int apic, int irq,
|
|
struct IO_APIC_route_entry *entry,
|
|
unsigned int destination, int trigger,
|
|
int polarity, int vector, int pin);
|
|
extern void ioapic_write_entry(int apic, int pin,
|
|
struct IO_APIC_route_entry e);
|
|
extern void setup_ioapic_ids_from_mpc(void);
|
|
|
|
struct mp_ioapic_gsi{
|
|
u32 gsi_base;
|
|
u32 gsi_end;
|
|
};
|
|
extern struct mp_ioapic_gsi mp_gsi_routing[];
|
|
extern u32 gsi_top;
|
|
int mp_find_ioapic(u32 gsi);
|
|
int mp_find_ioapic_pin(int ioapic, u32 gsi);
|
|
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
|
|
extern void __init pre_init_apic_IRQ0(void);
|
|
|
|
#else /* !CONFIG_X86_IO_APIC */
|
|
|
|
#define io_apic_assign_pci_irqs 0
|
|
#define setup_ioapic_ids_from_mpc x86_init_noop
|
|
static const int timer_through_8259 = 0;
|
|
static inline void ioapic_init_mappings(void) { }
|
|
static inline void ioapic_insert_resources(void) { }
|
|
static inline void probe_nr_irqs_gsi(void) { }
|
|
#define gsi_top (NR_IRQS_LEGACY)
|
|
static inline int mp_find_ioapic(u32 gsi) { return 0; }
|
|
|
|
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; }
|
|
#endif
|
|
|
|
#endif /* _ASM_X86_IO_APIC_H */
|