From: Philippe E. <ph...@us...> - 2002-11-01 04:20:09
|
Update of /cvsroot/oprofile/oprofile/module/x86 In directory usw-pr-cvs1:/tmp/cvs-serv10730/x86 Modified Files: op_apic.c Log Message: restore correctly lvtpc register rgards, Phil Index: op_apic.c =================================================================== RCS file: /cvsroot/oprofile/oprofile/module/x86/op_apic.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- op_apic.c 25 Sep 2002 14:46:47 -0000 1.9 +++ op_apic.c 1 Nov 2002 04:20:06 -0000 1.10 @@ -69,22 +69,19 @@ } /* ---------------- APIC setup ------------------ */ - -static uint lvtpc_old_mask[NR_CPUS]; -static uint lvtpc_old_mode[NR_CPUS]; +static uint saved_lvtpc[NR_CPUS]; void __init lvtpc_apic_setup(void * dummy) { uint val; - + /* set up LVTPC as we need it */ /* IA32 V3, Figure 7.8 */ val = apic_read(APIC_LVTPC); - lvtpc_old_mask[op_cpu_id()] = val & APIC_LVT_MASKED; + saved_lvtpc[op_cpu_id()] = val; /* allow PC overflow interrupts */ val &= ~APIC_LVT_MASKED; /* set delivery to NMI */ - lvtpc_old_mode[op_cpu_id()] = GET_APIC_DELIVERY_MODE(val); val = SET_APIC_DELIVERY_MODE(val, APIC_MODE_NMI); apic_write(APIC_LVTPC, val); } @@ -92,14 +89,15 @@ /* not safe to mark as __exit since used from __init code */ void lvtpc_apic_restore(void * dummy) { - uint val = apic_read(APIC_LVTPC); - // FIXME: this gives APIC errors on SMP hardware. - // val = SET_APIC_DELIVERY_MODE(val, lvtpc_old_mode[op_cpu_id()]); - if (lvtpc_old_mask[op_cpu_id()]) - val |= APIC_LVT_MASKED; - else - val &= ~APIC_LVT_MASKED; - apic_write(APIC_LVTPC, val); + /* restoring APIC_LVTPC can trigger an apic error because the delivery + * mode and vector nr combination can be illegal. That's by design: on + * power on apic lvt contain a zero vector nr which are legal only for + * NMI delivrey mode. So inhibit apic err before restoring lvtpc + */ + uint v = apic_read(APIC_LVTERR); + apic_write(APIC_LVTERR, v | APIC_LVT_MASKED); + apic_write(APIC_LVTPC, saved_lvtpc[op_cpu_id()]); + apic_write(APIC_LVTERR, v); } static int __init enable_apic(void) |