Home | History | Annotate | Download | only in x86
      1 /**
      2  * @file op_apic.c
      3  *
      4  * APIC setup etc. routines
      5  *
      6  * @remark Copyright 2002 OProfile authors
      7  * @remark Read the file COPYING
      8  *
      9  * @author John Levon
     10  * @author Philippe Elie
     11  * @author Dave Jones
     12  * @author Graydon Hoare
     13  */
     14 
     15 #include <linux/mm.h>
     16 #include <linux/init.h>
     17 #include <linux/config.h>
     18 #include <asm/io.h>
     19 
     20 #include "oprofile.h"
     21 #include "op_msr.h"
     22 #include "op_apic.h"
     23 
     24 /* used to save/restore original kernel nmi */
     25 static struct gate_struct kernel_nmi;
     26 static ulong lvtpc_masked;
     27 
     28 /* this masking code is unsafe and nasty but might deal with the small
     29  * race when installing the NMI entry into the IDT.
     30  */
     31 static void mask_lvtpc(void * e)
     32 {
     33 	u32 v = apic_read(APIC_LVTPC);
     34 	lvtpc_masked = v & APIC_LVT_MASKED;
     35 	apic_write(APIC_LVTPC, v | APIC_LVT_MASKED);
     36 }
     37 
     38 static void unmask_lvtpc(void * e)
     39 {
     40 	if (!lvtpc_masked)
     41 		apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
     42 }
     43 
     44 
     45 void install_nmi(void)
     46 {
     47 	struct _descr descr;
     48 
     49 	/* NMI handler is at idt_table[IDT_VECTOR_NUMBER]            */
     50 	/* see Intel Vol.3 Figure 5-2, interrupt gate                */
     51 
     52 	smp_call_function(mask_lvtpc, NULL, 0, 1);
     53 	mask_lvtpc(NULL);
     54 
     55 	store_idt(descr);
     56 	kernel_nmi = descr.base[NMI_VECTOR_NUM];
     57 	SET_NMI_GATE;
     58 
     59 	smp_call_function(unmask_lvtpc, NULL, 0, 1);
     60 	unmask_lvtpc(NULL);
     61 }
     62 
     63 void restore_nmi(void)
     64 {
     65 	struct _descr descr;
     66 
     67 	smp_call_function(mask_lvtpc, NULL, 0, 1);
     68 	mask_lvtpc(NULL);
     69 
     70 	store_idt(descr);
     71 	descr.base[NMI_VECTOR_NUM] = kernel_nmi;
     72 
     73 	smp_call_function(unmask_lvtpc, NULL, 0, 1);
     74 	unmask_lvtpc(NULL);
     75 }
     76 
     77 
     78 /* ---------------- APIC setup ------------------ */
     79 static uint saved_lvtpc[NR_CPUS];
     80 
     81 void __init lvtpc_apic_setup(void * dummy)
     82 {
     83 	uint val;
     84 
     85 	/* set up LVTPC as we need it */
     86 	/* IA32 V3, Figure 7.8 */
     87 	val = apic_read(APIC_LVTPC);
     88 	saved_lvtpc[op_cpu_id()] = val;
     89 	/* allow PC overflow interrupts */
     90 	val &= ~APIC_LVT_MASKED;
     91 	/* set delivery to NMI */
     92 	val = SET_APIC_DELIVERY_MODE(val, APIC_MODE_NMI);
     93 	apic_write(APIC_LVTPC, val);
     94 }
     95 
     96 /* not safe to mark as __exit since used from __init code */
     97 void lvtpc_apic_restore(void * dummy)
     98 {
     99 	/* restoring APIC_LVTPC can trigger an apic error because the delivery
    100 	 * mode and vector nr combination can be illegal. That's by design: on
    101 	 * power on apic lvt contain a zero vector nr which are legal only for
    102 	 * NMI delivrey mode. So inhibit apic err before restoring lvtpc
    103 	 */
    104 	uint v = apic_read(APIC_LVTERR);
    105 	apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
    106 	apic_write(APIC_LVTPC, saved_lvtpc[op_cpu_id()]);
    107 	apic_write(APIC_LVTERR, v);
    108 }
    109 
    110 static int __init enable_apic(void)
    111 {
    112 	uint msr_low, msr_high;
    113 	uint val;
    114 
    115 	/* enable local APIC via MSR. Forgetting this is a fun way to
    116 	 * lock the box. But we have to hope this is allowed if the APIC
    117 	 * has already been enabled.
    118 	 *
    119 	 * IA32 V3, 7.4.2 */
    120 	rdmsr(MSR_IA32_APICBASE, msr_low, msr_high);
    121 	if ((msr_low & (1 << 11)) == 0)
    122 		wrmsr(MSR_IA32_APICBASE, msr_low | (1 << 11), msr_high);
    123 
    124 	/* even if the apic is up we must check for a good APIC */
    125 
    126 	/* IA32 V3, 7.4.15 */
    127 	val = apic_read(APIC_LVR);
    128 	if (!APIC_INTEGRATED(GET_APIC_VERSION(val)))
    129 		goto not_local_apic;
    130 
    131 	/* LVT0,LVT1,LVTT,LVTPC */
    132 	if (GET_APIC_MAXLVT(apic_read(APIC_LVR)) < 4)
    133 		goto not_local_apic;
    134 
    135 	/* IA32 V3, 7.4.14.1 */
    136 	val = apic_read(APIC_SPIV);
    137 	if (!(val & APIC_SPIV_APIC_ENABLED))
    138 		apic_write(APIC_SPIV, val | APIC_SPIV_APIC_ENABLED);
    139 
    140 	return !!(val & APIC_SPIV_APIC_ENABLED);
    141 
    142 not_local_apic:
    143 	/* disable the apic only if it was disabled */
    144 	if ((msr_low & (1 << 11)) == 0)
    145 		wrmsr(MSR_IA32_APICBASE, msr_low & ~(1 << 11), msr_high);
    146 
    147 	printk(KERN_ERR "oprofile: no suitable local APIC. Falling back to RTC mode.\n");
    148 	return -ENODEV;
    149 }
    150 
    151 static void __init do_apic_setup(void)
    152 {
    153 	uint val;
    154 
    155 	local_irq_disable();
    156 
    157 	val = APIC_LVT_LEVEL_TRIGGER;
    158 	val = SET_APIC_DELIVERY_MODE(val, APIC_MODE_EXINT);
    159 	apic_write(APIC_LVT0, val);
    160 
    161 	/* edge triggered, IA 7.4.11 */
    162 	val = SET_APIC_DELIVERY_MODE(0, APIC_MODE_NMI);
    163 	apic_write(APIC_LVT1, val);
    164 
    165 	/* clear error register */
    166 	/* IA32 V3, 7.4.17 */
    167 	/* PHE must be cleared after unmasking by a back-to-back write,
    168 	 * but it is probably ok because we mask only, the ESR is not
    169 	 * updated is this a real problem ? */
    170 	apic_write(APIC_ESR, 0);
    171 
    172 	/* mask error interrupt */
    173 	/* IA32 V3, Figure 7.8 */
    174 	val = apic_read(APIC_LVTERR);
    175 	val |= APIC_LVT_MASKED;
    176 	apic_write(APIC_LVTERR, val);
    177 
    178 	/* setup timer vector */
    179 	/* IA32 V3, 7.4.8 */
    180 	apic_write(APIC_LVTT, APIC_SEND_PENDING | 0x31);
    181 
    182 	/* Divide configuration register */
    183 	/* PHE the apic clock is based on the FSB. This should only
    184 	 * changed with a calibration method.  */
    185 	val = APIC_TDR_DIV_1;
    186 	apic_write(APIC_TDCR, val);
    187 
    188 	local_irq_enable();
    189 }
    190 
    191 /* does the CPU have a local APIC ? */
    192 static int __init check_cpu_ok(void)
    193 {
    194 	if (sysctl.cpu_type != CPU_PPRO &&
    195 		sysctl.cpu_type != CPU_PII &&
    196 		sysctl.cpu_type != CPU_PIII &&
    197 		sysctl.cpu_type != CPU_ATHLON &&
    198 		sysctl.cpu_type != CPU_HAMMER &&
    199 		sysctl.cpu_type != CPU_P4 &&
    200 		sysctl.cpu_type != CPU_P4_HT2)
    201 		return 0;
    202 
    203 	return 1;
    204 }
    205 
    206 int __init apic_setup(void)
    207 {
    208 	u32 val;
    209 
    210 	if (!check_cpu_ok())
    211 		goto nodev;
    212 
    213 	fixmap_setup();
    214 
    215 	switch (enable_apic()) {
    216 		case 0:
    217 			do_apic_setup();
    218 			val = apic_read(APIC_ESR);
    219 			printk(KERN_INFO "oprofile: enabled local APIC. Err code %.08x\n", val);
    220 			break;
    221 		case 1:
    222 			printk(KERN_INFO "oprofile: APIC was already enabled\n");
    223 			break;
    224 		default:
    225 			goto nodev;
    226 	}
    227 
    228 	lvtpc_apic_setup(NULL);
    229 	return 0;
    230 nodev:
    231 	printk(KERN_WARNING "Your CPU does not have a local APIC, e.g. "
    232 	       "mobile P6. Falling back to RTC mode.\n");
    233 	return -ENODEV;
    234 }
    235 
    236 void apic_restore(void)
    237 {
    238 	fixmap_restore();
    239 }
    240