/**
 * @file op_apic.c
 *
 * APIC setup etc. routines
 *
 * @remark Copyright 2002 OProfile authors
 * @remark Read the file COPYING
 *
 * @author John Levon
 * @author Philippe Elie
 * @author Dave Jones
 * @author Graydon Hoare
 */

#include <linux/mm.h>
#include <linux/init.h>
#include <linux/config.h>
#include <asm/io.h>

#include "oprofile.h"
#include "op_msr.h"
#include "op_apic.h"

/* used to save/restore original kernel nmi */
static struct gate_struct kernel_nmi;
static ulong lvtpc_masked;

/* this masking code is unsafe and nasty but might deal with the small
 * race when installing the NMI entry into the IDT.
 */
static void mask_lvtpc(void * e)
{
	u32 v = apic_read(APIC_LVTPC);
	lvtpc_masked = v & APIC_LVT_MASKED;
	apic_write(APIC_LVTPC, v | APIC_LVT_MASKED);
}

static void unmask_lvtpc(void * e)
{
	if (!lvtpc_masked)
		apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
}


void install_nmi(void)
{
	struct _descr descr;

	/* NMI handler is at idt_table[IDT_VECTOR_NUMBER]            */
	/* see Intel Vol.3 Figure 5-2, interrupt gate                */

	smp_call_function(mask_lvtpc, NULL, 0, 1);
	mask_lvtpc(NULL);

	store_idt(descr);
	kernel_nmi = descr.base[NMI_VECTOR_NUM];
	SET_NMI_GATE;

	smp_call_function(unmask_lvtpc, NULL, 0, 1);
	unmask_lvtpc(NULL);
}

void restore_nmi(void)
{
	struct _descr descr;

	smp_call_function(mask_lvtpc, NULL, 0, 1);
	mask_lvtpc(NULL);

	store_idt(descr);
	descr.base[NMI_VECTOR_NUM] = kernel_nmi;

	smp_call_function(unmask_lvtpc, NULL, 0, 1);
	unmask_lvtpc(NULL);
}


/* ---------------- APIC setup ------------------ */
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);
	saved_lvtpc[op_cpu_id()] = val;
	/* allow PC overflow interrupts */
	val &= ~APIC_LVT_MASKED;
	/* set delivery to NMI */
	val = SET_APIC_DELIVERY_MODE(val, APIC_MODE_NMI);
	apic_write(APIC_LVTPC, val);
}

/* not safe to mark as __exit since used from __init code */
void lvtpc_apic_restore(void * dummy)
{
	/* 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)
{
	uint msr_low, msr_high;
	uint val;

	/* enable local APIC via MSR. Forgetting this is a fun way to
	 * lock the box. But we have to hope this is allowed if the APIC
	 * has already been enabled.
	 *
	 * IA32 V3, 7.4.2 */
	rdmsr(MSR_IA32_APICBASE, msr_low, msr_high);
	if ((msr_low & (1 << 11)) == 0)
		wrmsr(MSR_IA32_APICBASE, msr_low | (1<<11), msr_high);

	/* even if the apic is up we must check for a good APIC */

	/* IA32 V3, 7.4.15 */
	val = apic_read(APIC_LVR);
	if (!APIC_INTEGRATED(GET_APIC_VERSION(val)))
		goto not_local_apic;

	/* LVT0,LVT1,LVTT,LVTPC */
	if (GET_APIC_MAXLVT(apic_read(APIC_LVR)) < 4)
		goto not_local_apic;

	/* IA32 V3, 7.4.14.1 */
	val = apic_read(APIC_SPIV);
	if (!(val & APIC_SPIV_APIC_ENABLED))
		apic_write(APIC_SPIV, val | APIC_SPIV_APIC_ENABLED);

	return !!(val & APIC_SPIV_APIC_ENABLED);

not_local_apic:
	/* disable the apic only if it was disabled */
	if ((msr_low & (1 << 11)) == 0)
		wrmsr(MSR_IA32_APICBASE, msr_low & ~(1<<11), msr_high);

	printk(KERN_ERR "oprofile: no suitable local APIC. Falling back to RTC mode.\n");
	return -ENODEV;
}

static void __init do_apic_setup(void)
{
	uint val;

	local_irq_disable();

	val = APIC_LVT_LEVEL_TRIGGER;
	val = SET_APIC_DELIVERY_MODE(val, APIC_MODE_EXINT);
	apic_write(APIC_LVT0, val);

	/* edge triggered, IA 7.4.11 */
	val = SET_APIC_DELIVERY_MODE(0, APIC_MODE_NMI);
	apic_write(APIC_LVT1, val);

	/* clear error register */
	/* IA32 V3, 7.4.17 */
	/* PHE must be cleared after unmasking by a back-to-back write,
	 * but it is probably ok because we mask only, the ESR is not
	 * updated is this a real problem ? */
	apic_write(APIC_ESR, 0);

	/* mask error interrupt */
	/* IA32 V3, Figure 7.8 */
	val = apic_read(APIC_LVTERR);
	val |= APIC_LVT_MASKED;
	apic_write(APIC_LVTERR, val);

	/* setup timer vector */
	/* IA32 V3, 7.4.8 */
	apic_write(APIC_LVTT, APIC_SEND_PENDING | 0x31);

	/* Divide configuration register */
	/* PHE the apic clock is based on the FSB. This should only
	 * changed with a calibration method.  */
	val = APIC_TDR_DIV_1;
	apic_write(APIC_TDCR, val);

	local_irq_enable();
}

/* does the CPU have a local APIC ? */
static int __init check_cpu_ok(void)
{
	if (sysctl.cpu_type != CPU_PPRO &&
		sysctl.cpu_type != CPU_PII &&
		sysctl.cpu_type != CPU_PIII &&
		sysctl.cpu_type != CPU_ATHLON &&
		sysctl.cpu_type != CPU_HAMMER &&
		sysctl.cpu_type != CPU_P4 &&
		sysctl.cpu_type != CPU_P4_HT2)
		return 0;

	return 1;
}

int __init apic_setup(void)
{
	u32 val;

	if (!check_cpu_ok())
		goto nodev;

	fixmap_setup();

	switch (enable_apic()) {
		case 0:
			do_apic_setup();
			val = apic_read(APIC_ESR);
			printk(KERN_INFO "oprofile: enabled local APIC. Err code %.08x\n", val);
			break;
		case 1:
			printk(KERN_INFO "oprofile: APIC was already enabled\n");
			break;
		default:
			goto nodev;
	}

	lvtpc_apic_setup(NULL);
	return 0;
nodev:
	printk(KERN_WARNING "Your CPU does not have a local APIC, e.g. "
	       "mobile P6. Falling back to RTC mode.\n");
	return -ENODEV;
}

void apic_restore(void)
{
	fixmap_restore();
}
