ia64/xen-unstable

changeset 5174:1f65ea0027f8

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>
author kaf24@firebug.cl.cam.ac.uk
date Thu May 26 16:09:52 2005 +0000 (2005-05-26)
parents 0e347f03a68c
children 3c8c7c46c4a8
files xen/arch/x86/nmi.c xen/arch/x86/setup.c xen/common/ac_timer.c xen/include/xen/ac_timer.h
line diff
     1.1 --- a/xen/arch/x86/nmi.c	Thu May 26 15:49:31 2005 +0000
     1.2 +++ b/xen/arch/x86/nmi.c	Thu May 26 16:09:52 2005 +0000
     1.3 @@ -29,9 +29,10 @@
     1.4  
     1.5  unsigned int nmi_watchdog = NMI_NONE;
     1.6  static unsigned int nmi_hz = HZ;
     1.7 -unsigned int nmi_perfctr_msr;	/* the MSR to reset in NMI handler */
     1.8 -
     1.9 -extern int logical_proc_id[];
    1.10 +static unsigned int nmi_perfctr_msr;	/* the MSR to reset in NMI handler */
    1.11 +static unsigned int nmi_p4_cccr_val;
    1.12 +static struct ac_timer nmi_timer[NR_CPUS];
    1.13 +static unsigned int nmi_timer_ticks[NR_CPUS];
    1.14  
    1.15  #define K7_EVNTSEL_ENABLE	(1 << 22)
    1.16  #define K7_EVNTSEL_INT		(1 << 20)
    1.17 @@ -50,10 +51,6 @@ extern int logical_proc_id[];
    1.18  #define MSR_P4_PERFCTR0		0x300
    1.19  #define MSR_P4_CCCR0		0x360
    1.20  #define P4_ESCR_EVENT_SELECT(N)	((N)<<25)
    1.21 -#define P4_ESCR_OS0		(1<<3)
    1.22 -#define P4_ESCR_USR0		(1<<2)
    1.23 -#define P4_ESCR_OS1		(1<<1)
    1.24 -#define P4_ESCR_USR1		(1<<0)
    1.25  #define P4_CCCR_OVF_PMI0	(1<<26)
    1.26  #define P4_CCCR_OVF_PMI1	(1<<27)
    1.27  #define P4_CCCR_THRESHOLD(N)	((N)<<20)
    1.28 @@ -63,24 +60,17 @@ extern int logical_proc_id[];
    1.29  #define P4_CCCR_ESCR_SELECT(N)	((N)<<13)
    1.30  #define P4_CCCR_ENABLE		(1<<12)
    1.31  /* 
    1.32 - * Set up IQ_COUNTER{0,1} to behave like a clock, by having IQ_CCCR{0,1} filter
    1.33 + * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
    1.34   * CRU_ESCR0 (with any non-null event selector) through a complemented
    1.35   * max threshold. [IA32-Vol3, Section 14.9.9] 
    1.36   */
    1.37  #define MSR_P4_IQ_COUNTER0	0x30C
    1.38 -#define MSR_P4_IQ_COUNTER1	0x30D
    1.39  #define MSR_P4_IQ_CCCR0		0x36C
    1.40 -#define MSR_P4_IQ_CCCR1		0x36D
    1.41  #define MSR_P4_CRU_ESCR0	0x3B8 /* ESCR no. 4 */
    1.42 -#define P4_NMI_CRU_ESCR0 \
    1.43 -    (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS0|P4_ESCR_USR0| \
    1.44 -     P4_ESCR_OS1|P4_ESCR_USR1)
    1.45 +#define P4_NMI_CRU_ESCR0	P4_ESCR_EVENT_SELECT(0x3F)
    1.46  #define P4_NMI_IQ_CCCR0	\
    1.47      (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
    1.48       P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
    1.49 -#define P4_NMI_IQ_CCCR1	\
    1.50 -    (P4_CCCR_OVF_PMI1|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|	\
    1.51 -     P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
    1.52  
    1.53  int __init check_nmi_watchdog (void)
    1.54  {
    1.55 @@ -118,6 +108,13 @@ int __init check_nmi_watchdog (void)
    1.56      return 0;
    1.57  }
    1.58  
    1.59 +static void nmi_timer_fn(void *unused)
    1.60 +{
    1.61 +    int cpu = smp_processor_id();
    1.62 +    nmi_timer_ticks[cpu]++;
    1.63 +    set_ac_timer(&nmi_timer[cpu], NOW() + MILLISECS(1000));
    1.64 +}
    1.65 +
    1.66  static inline void nmi_pm_init(void) { }
    1.67  #define __pminit	__init
    1.68  
    1.69 @@ -186,45 +183,35 @@ static int __pminit setup_p4_watchdog(vo
    1.70          return 0;
    1.71  
    1.72      nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
    1.73 +    nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
    1.74 +    if ( smp_num_siblings == 2 )
    1.75 +        nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
    1.76  
    1.77 -    if ( logical_proc_id[smp_processor_id()] == 0 )
    1.78 -    {
    1.79 -        if (!(misc_enable & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL))
    1.80 -            clear_msr_range(0x3F1, 2);
    1.81 -        /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
    1.82 -           docs doesn't fully define it, so leave it alone for now. */
    1.83 -        clear_msr_range(0x3A0, 31);
    1.84 -        clear_msr_range(0x3C0, 6);
    1.85 -        clear_msr_range(0x3C8, 6);
    1.86 -        clear_msr_range(0x3E0, 2);
    1.87 -        clear_msr_range(MSR_P4_CCCR0, 18);
    1.88 -        clear_msr_range(MSR_P4_PERFCTR0, 18);
    1.89 +    if (!(misc_enable & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL))
    1.90 +        clear_msr_range(0x3F1, 2);
    1.91 +    /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
    1.92 +       docs doesn't fully define it, so leave it alone for now. */
    1.93 +    clear_msr_range(0x3A0, 31);
    1.94 +    clear_msr_range(0x3C0, 6);
    1.95 +    clear_msr_range(0x3C8, 6);
    1.96 +    clear_msr_range(0x3E0, 2);
    1.97 +    clear_msr_range(MSR_P4_CCCR0, 18);
    1.98 +    clear_msr_range(MSR_P4_PERFCTR0, 18);
    1.99          
   1.100 -        wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
   1.101 -        wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
   1.102 -        Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
   1.103 -        wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
   1.104 -        apic_write(APIC_LVTPC, APIC_DM_NMI);
   1.105 -        wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
   1.106 -    }
   1.107 -    else if ( logical_proc_id[smp_processor_id()] == 1 )
   1.108 -    {
   1.109 -        wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1 & ~P4_CCCR_ENABLE, 0);
   1.110 -        Dprintk("setting P4_IQ_COUNTER2 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
   1.111 -        wrmsr(MSR_P4_IQ_COUNTER1, -(cpu_khz/nmi_hz*1000), -1);
   1.112 -        apic_write(APIC_LVTPC, APIC_DM_NMI);
   1.113 -        wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1, 0);        
   1.114 -    }
   1.115 -    else
   1.116 -    {
   1.117 -        return 0;
   1.118 -    }
   1.119 +    wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
   1.120 +    wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
   1.121 +    Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
   1.122 +    wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
   1.123 +    apic_write(APIC_LVTPC, APIC_DM_NMI);
   1.124 +    wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
   1.125  
   1.126      return 1;
   1.127  }
   1.128  
   1.129  void __pminit setup_apic_nmi_watchdog(void)
   1.130  {
   1.131 +    int cpu = smp_processor_id();
   1.132 +
   1.133      if (!nmi_watchdog)
   1.134          return;
   1.135  
   1.136 @@ -250,6 +237,10 @@ void __pminit setup_apic_nmi_watchdog(vo
   1.137      default:
   1.138          return;
   1.139      }
   1.140 +
   1.141 +    init_ac_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu);
   1.142 +    nmi_timer_fn(NULL);
   1.143 +
   1.144      nmi_pm_init();
   1.145  }
   1.146  
   1.147 @@ -280,11 +271,11 @@ void watchdog_enable(void)
   1.148      spin_unlock_irqrestore(&watchdog_lock, flags);
   1.149  }
   1.150  
   1.151 -void nmi_watchdog_tick (struct cpu_user_regs * regs)
   1.152 +void nmi_watchdog_tick(struct cpu_user_regs * regs)
   1.153  {
   1.154      int sum, cpu = smp_processor_id();
   1.155  
   1.156 -    sum = ac_timers[cpu].softirqs;
   1.157 +    sum = nmi_timer_ticks[cpu];
   1.158  
   1.159      if ( (last_irq_sums[cpu] == sum) && watchdog_on )
   1.160      {
   1.161 @@ -310,22 +301,24 @@ void nmi_watchdog_tick (struct cpu_user_
   1.162      {
   1.163          if ( nmi_perfctr_msr == MSR_P4_IQ_COUNTER0 )
   1.164          {
   1.165 -            if ( logical_proc_id[cpu] == 0 )
   1.166 -            {
   1.167 -                wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
   1.168 -                apic_write(APIC_LVTPC, APIC_DM_NMI);
   1.169 -                wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
   1.170 -            }
   1.171 -            else
   1.172 -            {
   1.173 -                wrmsr(MSR_P4_IQ_CCCR1, P4_NMI_IQ_CCCR1, 0);
   1.174 -                apic_write(APIC_LVTPC, APIC_DM_NMI);
   1.175 -                wrmsr(MSR_P4_IQ_COUNTER1, -(cpu_khz/nmi_hz*1000), -1);
   1.176 -            }
   1.177 +            /*
   1.178 +             * P4 quirks:
   1.179 +             * - An overflown perfctr will assert its interrupt
   1.180 +             *   until the OVF flag in its CCCR is cleared.
   1.181 +             * - LVTPC is masked on interrupt and must be
   1.182 +             *   unmasked by the LVTPC handler.
   1.183 +             */
   1.184 +            wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
   1.185 +            apic_write(APIC_LVTPC, APIC_DM_NMI);
   1.186          }
   1.187 -        else
   1.188 +        else if ( nmi_perfctr_msr == MSR_P6_PERFCTR0 )
   1.189          {
   1.190 -            wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
   1.191 +            /*
   1.192 +             * Only P6 based Pentium M need to re-unmask the apic vector but
   1.193 +             * it doesn't hurt other P6 variants.
   1.194 +             */
   1.195 +            apic_write(APIC_LVTPC, APIC_DM_NMI);
   1.196          }
   1.197 +        wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
   1.198      }
   1.199  }
     2.1 --- a/xen/arch/x86/setup.c	Thu May 26 15:49:31 2005 +0000
     2.2 +++ b/xen/arch/x86/setup.c	Thu May 26 16:09:52 2005 +0000
     2.3 @@ -100,8 +100,6 @@ struct exec_domain *idle_task[NR_CPUS] =
     2.4  
     2.5  int acpi_disabled;
     2.6  
     2.7 -int logical_proc_id[NR_CPUS];
     2.8 -
     2.9  int acpi_force;
    2.10  char acpi_param[10] = "";
    2.11  static void parse_acpi_param(char *s)
    2.12 @@ -196,6 +194,8 @@ static void __init start_of_day(void)
    2.13  
    2.14      trap_init();
    2.15  
    2.16 +    ac_timer_init();
    2.17 +
    2.18      time_init();
    2.19  
    2.20      arch_init_memory();
    2.21 @@ -215,8 +215,6 @@ static void __init start_of_day(void)
    2.22  
    2.23      serial_init_stage2();
    2.24  
    2.25 -    ac_timer_init();
    2.26 -
    2.27      init_xen_time();
    2.28  
    2.29      for_each_present_cpu ( i )
     3.1 --- a/xen/common/ac_timer.c	Thu May 26 15:49:31 2005 +0000
     3.2 +++ b/xen/common/ac_timer.c	Thu May 26 16:09:52 2005 +0000
     3.3 @@ -26,8 +26,16 @@
     3.4   */
     3.5  #define TIMER_SLOP (50*1000) /* ns */
     3.6  
     3.7 +struct ac_timers {
     3.8 +    spinlock_t        lock;
     3.9 +    struct ac_timer **heap;
    3.10 +    unsigned int      softirqs;
    3.11 +} __cacheline_aligned;
    3.12 +
    3.13  struct ac_timers ac_timers[NR_CPUS];
    3.14  
    3.15 +extern int reprogram_ac_timer(s_time_t timeout);
    3.16 +
    3.17  /****************************************************************************
    3.18   * HEAP OPERATIONS.
    3.19   */
    3.20 @@ -189,8 +197,6 @@ static void ac_timer_softirq_action(void
    3.21      s_time_t         now;
    3.22      void             (*fn)(void *);
    3.23  
    3.24 -    ac_timers[cpu].softirqs++;
    3.25 -
    3.26      spin_lock_irq(&ac_timers[cpu].lock);
    3.27      
    3.28      do {
     4.1 --- a/xen/include/xen/ac_timer.h	Thu May 26 15:49:31 2005 +0000
     4.2 +++ b/xen/include/xen/ac_timer.h	Thu May 26 16:09:52 2005 +0000
     4.3 @@ -62,20 +62,6 @@ extern void set_ac_timer(struct ac_timer
     4.4   */
     4.5  extern void rem_ac_timer(struct ac_timer *timer);
     4.6  
     4.7 -
     4.8 -/*
     4.9 - * PRIVATE DEFINITIONS
    4.10 - */
    4.11 -
    4.12 -extern int reprogram_ac_timer(s_time_t timeout);
    4.13 -
    4.14 -struct ac_timers {
    4.15 -    spinlock_t        lock;
    4.16 -    struct ac_timer **heap;
    4.17 -    unsigned int      softirqs;
    4.18 -} __cacheline_aligned;
    4.19 -extern struct ac_timers ac_timers[];
    4.20 -
    4.21  #endif /* _AC_TIMER_H_ */
    4.22  
    4.23  /*