x86: Allow direct vectored interrupts to be dynamically allocated.

Use this for Intel's CMCI and thermal interrupts.

Signed-off-by: Keir Fraser <keir@xen.org>
This commit is contained in:
Keir Fraser committed 2012-03-30 09:14:25 +01:00
1 parent 33c4b1044d
commit bdc31d56d8
5 files changed
+59 -68

No files matched your search

-8
View File
@@ -128,14 +128,6 @@ void __init apic_intr_init(void)
/* Performance Counters Interrupt */
set_direct_apic_vector(PMU_APIC_VECTOR, pmu_apic_interrupt);
/* CMCI Correctable Machine Check Interrupt */
set_direct_apic_vector(CMCI_APIC_VECTOR, cmci_interrupt);
/* thermal monitor LVT interrupt, for P4 and latest Intel CPU*/
#ifdef CONFIG_X86_MCE_THERMAL
set_direct_apic_vector(THERMAL_APIC_VECTOR, thermal_interrupt);
#endif
}
/* Using APIC to generate smp_local_timer_interrupt? */
+39 -53
View File
@@ -46,22 +46,15 @@ static int __read_mostly nr_intel_ext_msrs;
#define INTEL_SRAR_DATA_LOAD 0x134
#define INTEL_SRAR_INSTR_FETCH 0x150
/* Thermal Hanlding */
#ifdef CONFIG_X86_MCE_THERMAL
static void unexpected_thermal_interrupt(struct cpu_user_regs *regs)
{
printk(KERN_ERR "Thermal: CPU%d: Unexpected LVT TMR interrupt!\n",
smp_processor_id());
add_taint(TAINT_MACHINE_CHECK);
}
/* P4/Xeon Thermal transition interrupt handler */
static void intel_thermal_interrupt(struct cpu_user_regs *regs)
{
uint64_t msr_content;
unsigned int cpu = smp_processor_id();
static DEFINE_PER_CPU(s_time_t, next);
ack_APIC_irq();
if (NOW() < per_cpu(next, cpu))
return;
@@ -77,16 +70,6 @@ static void intel_thermal_interrupt(struct cpu_user_regs *regs)
}
}
/* Thermal interrupt handler for this CPU setup */
static void (*__read_mostly vendor_thermal_interrupt)(
struct cpu_user_regs *regs) = unexpected_thermal_interrupt;
void thermal_interrupt(struct cpu_user_regs *regs)
{
ack_APIC_irq();
vendor_thermal_interrupt(regs);
}
/* Thermal monitoring depends on APIC, ACPI and clock modulation */
static int intel_thermal_supported(struct cpuinfo_x86 *c)
{
@@ -117,6 +100,7 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
uint32_t val;
int tm2 = 0;
unsigned int cpu = smp_processor_id();
static uint8_t thermal_apic_vector;
if (!intel_thermal_supported(c))
return; /* -ENODEV */
@@ -159,17 +143,16 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
return; /* -EBUSY */
}
alloc_direct_apic_vector(&thermal_apic_vector, intel_thermal_interrupt);
/* The temperature transition interrupt handler setup */
val = THERMAL_APIC_VECTOR; /* our delivery vector */
val = thermal_apic_vector; /* our delivery vector */
val |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */
apic_write_around(APIC_LVTTHMR, val);
rdmsrl(MSR_IA32_THERM_INTERRUPT, msr_content);
wrmsrl(MSR_IA32_THERM_INTERRUPT, msr_content | 0x03);
/* ok we're good to go... */
vendor_thermal_interrupt = intel_thermal_interrupt;
rdmsrl(MSR_IA32_MISC_ENABLE, msr_content);
wrmsrl(MSR_IA32_MISC_ENABLE, msr_content | (1ULL<<3));
@@ -1154,36 +1137,7 @@ static void cpu_mcheck_disable(void)
clear_cmci();
}
static void intel_init_cmci(struct cpuinfo_x86 *c)
{
u32 l, apic;
int cpu = smp_processor_id();
if (!mce_available(c) || !cmci_support) {
if (opt_cpu_info)
mce_printk(MCE_QUIET, "CMCI: CPU%d has no CMCI support\n", cpu);
return;
}
apic = apic_read(APIC_CMCI);
if ( apic & APIC_VECTOR_MASK )
{
mce_printk(MCE_QUIET, "CPU%d CMCI LVT vector (%#x) already installed\n",
cpu, ( apic & APIC_VECTOR_MASK ));
return;
}
apic = CMCI_APIC_VECTOR;
apic |= (APIC_DM_FIXED | APIC_LVT_MASKED);
apic_write_around(APIC_CMCI, apic);
l = apic_read(APIC_CMCI);
apic_write_around(APIC_CMCI, l & ~APIC_LVT_MASKED);
mce_set_owner();
}
void cmci_interrupt(struct cpu_user_regs *regs)
static void cmci_interrupt(struct cpu_user_regs *regs)
{
mctelem_cookie_t mctc;
struct mca_summary bs;
@@ -1206,6 +1160,38 @@ void cmci_interrupt(struct cpu_user_regs *regs)
mctelem_dismiss(mctc);
}
static void intel_init_cmci(struct cpuinfo_x86 *c)
{
u32 l, apic;
int cpu = smp_processor_id();
static uint8_t cmci_apic_vector;
if (!mce_available(c) || !cmci_support) {
if (opt_cpu_info)
mce_printk(MCE_QUIET, "CMCI: CPU%d has no CMCI support\n", cpu);
return;
}
apic = apic_read(APIC_CMCI);
if ( apic & APIC_VECTOR_MASK )
{
mce_printk(MCE_QUIET, "CPU%d CMCI LVT vector (%#x) already installed\n",
cpu, ( apic & APIC_VECTOR_MASK ));
return;
}
alloc_direct_apic_vector(&cmci_apic_vector, cmci_interrupt);
apic = cmci_apic_vector;
apic |= (APIC_DM_FIXED | APIC_LVT_MASKED);
apic_write_around(APIC_CMCI, apic);
l = apic_read(APIC_CMCI);
apic_write_around(APIC_CMCI, l & ~APIC_LVT_MASKED);
mce_set_owner();
}
/* MCA */
static int mce_is_broadcast(struct cpuinfo_x86 *c)
+15
View File
@@ -772,6 +772,21 @@ void set_direct_apic_vector(
direct_apic_vector[vector] = handler;
}
void alloc_direct_apic_vector(
uint8_t *vector, void (*handler)(struct cpu_user_regs *))
{
static uint8_t next = LAST_HIPRIORITY_VECTOR;
static DEFINE_SPINLOCK(lock);
spin_lock(&lock);
if (*vector == 0) {
BUG_ON(next == FIRST_HIPRIORITY_VECTOR);
set_direct_apic_vector(next, handler);
*vector = next--;
}
spin_unlock(&lock);
}
void do_IRQ(struct cpu_user_regs *regs)
{
struct irqaction *action;
+2 -2
View File
@@ -86,12 +86,12 @@ void apic_timer_interrupt(struct cpu_user_regs *regs);
void error_interrupt(struct cpu_user_regs *regs);
void pmu_apic_interrupt(struct cpu_user_regs *regs);
void spurious_interrupt(struct cpu_user_regs *regs);
void thermal_interrupt(struct cpu_user_regs *regs);
void cmci_interrupt(struct cpu_user_regs *regs);
void irq_move_cleanup_interrupt(struct cpu_user_regs *regs);
void set_direct_apic_vector(
uint8_t vector, void (*handler)(struct cpu_user_regs *));
void alloc_direct_apic_vector(
uint8_t *vector, void (*handler)(struct cpu_user_regs *));
void do_IRQ(struct cpu_user_regs *regs);
@@ -7,16 +7,14 @@
#define INVALIDATE_TLB_VECTOR 0xfd
#define EVENT_CHECK_VECTOR 0xfc
#define CALL_FUNCTION_VECTOR 0xfb
#define THERMAL_APIC_VECTOR 0xfa
#define LOCAL_TIMER_VECTOR 0xf9
#define PMU_APIC_VECTOR 0xf8
#define CMCI_APIC_VECTOR 0xf7
#define LOCAL_TIMER_VECTOR 0xfa
#define PMU_APIC_VECTOR 0xf9
/*
* High-priority dynamically-allocated vectors. For interrupts that
* must be higher priority than any guest-bound interrupt.
*/
#define FIRST_HIPRIORITY_VECTOR 0xf0
#define LAST_HIPRIORITY_VECTOR 0xf6
#define LAST_HIPRIORITY_VECTOR 0xf8
/* Legacy PIC uses vectors 0xe0-0xef. */
#define FIRST_LEGACY_VECTOR 0xe0
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.