mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.1566 (4295f4d0ecoRI1FVDrCqrrfgF5j8ug)
Clean up NMI watchdog handler. No need to hack into ac_timer structs. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
cc351a6ce9
commit
2a2bd8de16
4 files changed
+66
-83
No files matched your search
+56
-63
@@ -29,9 +29,10 @@
|
|||||||
|
|
||||||
unsigned int nmi_watchdog = NMI_NONE;
|
unsigned int nmi_watchdog = NMI_NONE;
|
||||||
static unsigned int nmi_hz = HZ;
|
static unsigned int nmi_hz = HZ;
|
||||||
unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
|
static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
|
||||||
|
static unsigned int nmi_p4_cccr_val;
|
||||||
extern int logical_proc_id[];
|
static struct ac_timer nmi_timer[NR_CPUS];
|
||||||
|
static unsigned int nmi_timer_ticks[NR_CPUS];
|
||||||
|
|
||||||
#define K7_EVNTSEL_ENABLE (1 << 22)
|
#define K7_EVNTSEL_ENABLE (1 << 22)
|
||||||
#define K7_EVNTSEL_INT (1 << 20)
|
#define K7_EVNTSEL_INT (1 << 20)
|
||||||
@@ -50,10 +51,6 @@ extern int logical_proc_id[];
|
|||||||
#define MSR_P4_PERFCTR0 0x300
|
#define MSR_P4_PERFCTR0 0x300
|
||||||
#define MSR_P4_CCCR0 0x360
|
#define MSR_P4_CCCR0 0x360
|
||||||
#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
|
#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
|
||||||
#define P4_ESCR_OS0 (1<<3)
|
|
||||||
#define P4_ESCR_USR0 (1<<2)
|
|
||||||
#define P4_ESCR_OS1 (1<<1)
|
|
||||||
#define P4_ESCR_USR1 (1<<0)
|
|
||||||
#define P4_CCCR_OVF_PMI0 (1<<26)
|
#define P4_CCCR_OVF_PMI0 (1<<26)
|
||||||
#define P4_CCCR_OVF_PMI1 (1<<27)
|
#define P4_CCCR_OVF_PMI1 (1<<27)
|
||||||
#define P4_CCCR_THRESHOLD(N) ((N)<<20)
|
#define P4_CCCR_THRESHOLD(N) ((N)<<20)
|
||||||
@@ -63,24 +60,17 @@ extern int logical_proc_id[];
|
|||||||
#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
|
#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
|
||||||
#define P4_CCCR_ENABLE (1<<12)
|
#define P4_CCCR_ENABLE (1<<12)
|
||||||
/*
|
/*
|
||||||
* Set up IQ_COUNTER{0,1} to behave like a clock, by having IQ_CCCR{0,1} filter
|
* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
|
||||||
* CRU_ESCR0 (with any non-null event selector) through a complemented
|
* CRU_ESCR0 (with any non-null event selector) through a complemented
|
||||||
* max threshold. [IA32-Vol3, Section 14.9.9]
|
* max threshold. [IA32-Vol3, Section 14.9.9]
|
||||||
*/
|
*/
|
||||||
#define MSR_P4_IQ_COUNTER0 0x30C
|
#define MSR_P4_IQ_COUNTER0 0x30C
|
||||||
#define MSR_P4_IQ_COUNTER1 0x30D
|
|
||||||
#define MSR_P4_IQ_CCCR0 0x36C
|
#define MSR_P4_IQ_CCCR0 0x36C
|
||||||
#define MSR_P4_IQ_CCCR1 0x36D
|
|
||||||
#define MSR_P4_CRU_ESCR0 0x3B8 /* ESCR no. 4 */
|
#define MSR_P4_CRU_ESCR0 0x3B8 /* ESCR no. 4 */
|
||||||
#define P4_NMI_CRU_ESCR0 \
|
#define P4_NMI_CRU_ESCR0 P4_ESCR_EVENT_SELECT(0x3F)
|
||||||
(P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS0|P4_ESCR_USR0| \
|
|
||||||
P4_ESCR_OS1|P4_ESCR_USR1)
|
|
||||||
#define P4_NMI_IQ_CCCR0 \
|
#define P4_NMI_IQ_CCCR0 \
|
||||||
(P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
|
(P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
|
||||||
P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
|
P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
|
||||||
#define P4_NMI_IQ_CCCR1 \
|
|
||||||
(P4_CCCR_OVF_PMI1|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
|
|
||||||
P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
|
|
||||||
|
|
||||||
int __init check_nmi_watchdog (void)
|
int __init check_nmi_watchdog (void)
|
||||||
{
|
{
|
||||||
@@ -118,6 +108,13 @@ int __init check_nmi_watchdog (void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nmi_timer_fn(void *unused)
|
||||||
|
{
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
nmi_timer_ticks[cpu]++;
|
||||||
|
set_ac_timer(&nmi_timer[cpu], NOW() + MILLISECS(1000));
|
||||||
|
}
|
||||||
|
|
||||||
static inline void nmi_pm_init(void) { }
|
static inline void nmi_pm_init(void) { }
|
||||||
#define __pminit __init
|
#define __pminit __init
|
||||||
|
|
||||||
@@ -186,45 +183,35 @@ static int __pminit setup_p4_watchdog(void)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
|
nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
|
||||||
|
nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
|
||||||
|
if ( smp_num_siblings == 2 )
|
||||||
|
nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
|
||||||
|
|
||||||
if ( logical_proc_id[smp_processor_id()] == 0 )
|
if (!(misc_enable & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL))
|
||||||
{
|
clear_msr_range(0x3F1, 2);
|
||||||
if (!(misc_enable & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL))
|
/* MSR 0x3F0 seems to have a default value of 0xFC00, but current
|
||||||
clear_msr_range(0x3F1, 2);
|
docs doesn't fully define it, so leave it alone for now. */
|
||||||
/* MSR 0x3F0 seems to have a default value of 0xFC00, but current
|
clear_msr_range(0x3A0, 31);
|
||||||
docs doesn't fully define it, so leave it alone for now. */
|
clear_msr_range(0x3C0, 6);
|
||||||
clear_msr_range(0x3A0, 31);
|
clear_msr_range(0x3C8, 6);
|
||||||
clear_msr_range(0x3C0, 6);
|
clear_msr_range(0x3E0, 2);
|
||||||
clear_msr_range(0x3C8, 6);
|
clear_msr_range(MSR_P4_CCCR0, 18);
|
||||||
clear_msr_range(0x3E0, 2);
|
clear_msr_range(MSR_P4_PERFCTR0, 18);
|
||||||
clear_msr_range(MSR_P4_CCCR0, 18);
|
|
||||||
clear_msr_range(MSR_P4_PERFCTR0, 18);
|
|
||||||
|
|
||||||
wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
|
wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
|
||||||
wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
|
wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
|
||||||
Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
|
Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
|
||||||
wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
|
wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
|
||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
||||||
wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
|
wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
|
||||||
}
|
|
||||||
else if ( logical_proc_id[smp_processor_id()] == 1 )
|
|
||||||
{
|
|
||||||
wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1 & ~P4_CCCR_ENABLE, 0);
|
|
||||||
Dprintk("setting P4_IQ_COUNTER2 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
|
|
||||||
wrmsr(MSR_P4_IQ_COUNTER1, -(cpu_khz/nmi_hz*1000), -1);
|
|
||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
|
||||||
wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __pminit setup_apic_nmi_watchdog(void)
|
void __pminit setup_apic_nmi_watchdog(void)
|
||||||
{
|
{
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
if (!nmi_watchdog)
|
if (!nmi_watchdog)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -250,6 +237,10 @@ void __pminit setup_apic_nmi_watchdog(void)
|
|||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_ac_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu);
|
||||||
|
nmi_timer_fn(NULL);
|
||||||
|
|
||||||
nmi_pm_init();
|
nmi_pm_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,11 +271,11 @@ void watchdog_enable(void)
|
|||||||
spin_unlock_irqrestore(&watchdog_lock, flags);
|
spin_unlock_irqrestore(&watchdog_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nmi_watchdog_tick (struct cpu_user_regs * regs)
|
void nmi_watchdog_tick(struct cpu_user_regs * regs)
|
||||||
{
|
{
|
||||||
int sum, cpu = smp_processor_id();
|
int sum, cpu = smp_processor_id();
|
||||||
|
|
||||||
sum = ac_timers[cpu].softirqs;
|
sum = nmi_timer_ticks[cpu];
|
||||||
|
|
||||||
if ( (last_irq_sums[cpu] == sum) && watchdog_on )
|
if ( (last_irq_sums[cpu] == sum) && watchdog_on )
|
||||||
{
|
{
|
||||||
@@ -310,22 +301,24 @@ void nmi_watchdog_tick (struct cpu_user_regs * regs)
|
|||||||
{
|
{
|
||||||
if ( nmi_perfctr_msr == MSR_P4_IQ_COUNTER0 )
|
if ( nmi_perfctr_msr == MSR_P4_IQ_COUNTER0 )
|
||||||
{
|
{
|
||||||
if ( logical_proc_id[cpu] == 0 )
|
/*
|
||||||
{
|
* P4 quirks:
|
||||||
wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
|
* - An overflown perfctr will assert its interrupt
|
||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
* until the OVF flag in its CCCR is cleared.
|
||||||
wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
|
* - LVTPC is masked on interrupt and must be
|
||||||
}
|
* unmasked by the LVTPC handler.
|
||||||
else
|
*/
|
||||||
{
|
wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
|
||||||
wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1, 0);
|
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
||||||
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
|
||||||
wrmsr(MSR_P4_IQ_COUNTER1, -(cpu_khz/nmi_hz*1000), -1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else if ( nmi_perfctr_msr == MSR_P6_PERFCTR0 )
|
||||||
{
|
{
|
||||||
wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
|
/*
|
||||||
|
* Only P6 based Pentium M need to re-unmask the apic vector but
|
||||||
|
* it doesn't hurt other P6 variants.
|
||||||
|
*/
|
||||||
|
apic_write(APIC_LVTPC, APIC_DM_NMI);
|
||||||
}
|
}
|
||||||
|
wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,8 +100,6 @@ struct exec_domain *idle_task[NR_CPUS] = { &idle0_exec_domain };
|
|||||||
|
|
||||||
int acpi_disabled;
|
int acpi_disabled;
|
||||||
|
|
||||||
int logical_proc_id[NR_CPUS];
|
|
||||||
|
|
||||||
int acpi_force;
|
int acpi_force;
|
||||||
char acpi_param[10] = "";
|
char acpi_param[10] = "";
|
||||||
static void parse_acpi_param(char *s)
|
static void parse_acpi_param(char *s)
|
||||||
@@ -196,6 +194,8 @@ static void __init start_of_day(void)
|
|||||||
|
|
||||||
trap_init();
|
trap_init();
|
||||||
|
|
||||||
|
ac_timer_init();
|
||||||
|
|
||||||
time_init();
|
time_init();
|
||||||
|
|
||||||
arch_init_memory();
|
arch_init_memory();
|
||||||
@@ -215,8 +215,6 @@ static void __init start_of_day(void)
|
|||||||
|
|
||||||
serial_init_stage2();
|
serial_init_stage2();
|
||||||
|
|
||||||
ac_timer_init();
|
|
||||||
|
|
||||||
init_xen_time();
|
init_xen_time();
|
||||||
|
|
||||||
for_each_present_cpu ( i )
|
for_each_present_cpu ( i )
|
||||||
|
|||||||
@@ -26,8 +26,16 @@
|
|||||||
*/
|
*/
|
||||||
#define TIMER_SLOP (50*1000) /* ns */
|
#define TIMER_SLOP (50*1000) /* ns */
|
||||||
|
|
||||||
|
struct ac_timers {
|
||||||
|
spinlock_t lock;
|
||||||
|
struct ac_timer **heap;
|
||||||
|
unsigned int softirqs;
|
||||||
|
} __cacheline_aligned;
|
||||||
|
|
||||||
struct ac_timers ac_timers[NR_CPUS];
|
struct ac_timers ac_timers[NR_CPUS];
|
||||||
|
|
||||||
|
extern int reprogram_ac_timer(s_time_t timeout);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* HEAP OPERATIONS.
|
* HEAP OPERATIONS.
|
||||||
*/
|
*/
|
||||||
@@ -189,8 +197,6 @@ static void ac_timer_softirq_action(void)
|
|||||||
s_time_t now;
|
s_time_t now;
|
||||||
void (*fn)(void *);
|
void (*fn)(void *);
|
||||||
|
|
||||||
ac_timers[cpu].softirqs++;
|
|
||||||
|
|
||||||
spin_lock_irq(&ac_timers[cpu].lock);
|
spin_lock_irq(&ac_timers[cpu].lock);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -62,20 +62,6 @@ extern void set_ac_timer(struct ac_timer *timer, s_time_t expires);
|
|||||||
*/
|
*/
|
||||||
extern void rem_ac_timer(struct ac_timer *timer);
|
extern void rem_ac_timer(struct ac_timer *timer);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PRIVATE DEFINITIONS
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int reprogram_ac_timer(s_time_t timeout);
|
|
||||||
|
|
||||||
struct ac_timers {
|
|
||||||
spinlock_t lock;
|
|
||||||
struct ac_timer **heap;
|
|
||||||
unsigned int softirqs;
|
|
||||||
} __cacheline_aligned;
|
|
||||||
extern struct ac_timers ac_timers[];
|
|
||||||
|
|
||||||
#endif /* _AC_TIMER_H_ */
|
#endif /* _AC_TIMER_H_ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||