xref: /freebsd/sys/dev/hwpmc/hwpmc_x86.c (revision f263522a45b9cf5cfb83a40e3135aa7108764d60)
1f263522aSJoseph Koshy /*-
2f263522aSJoseph Koshy  * Copyright (c) 2005, Joseph Koshy
3f263522aSJoseph Koshy  * All rights reserved.
4f263522aSJoseph Koshy  *
5f263522aSJoseph Koshy  * Redistribution and use in source and binary forms, with or without
6f263522aSJoseph Koshy  * modification, are permitted provided that the following conditions
7f263522aSJoseph Koshy  * are met:
8f263522aSJoseph Koshy  * 1. Redistributions of source code must retain the above copyright
9f263522aSJoseph Koshy  *    notice, this list of conditions and the following disclaimer.
10f263522aSJoseph Koshy  * 2. Redistributions in binary form must reproduce the above copyright
11f263522aSJoseph Koshy  *    notice, this list of conditions and the following disclaimer in the
12f263522aSJoseph Koshy  *    documentation and/or other materials provided with the distribution.
13f263522aSJoseph Koshy  *
14f263522aSJoseph Koshy  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15f263522aSJoseph Koshy  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16f263522aSJoseph Koshy  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17f263522aSJoseph Koshy  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18f263522aSJoseph Koshy  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19f263522aSJoseph Koshy  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20f263522aSJoseph Koshy  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21f263522aSJoseph Koshy  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22f263522aSJoseph Koshy  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23f263522aSJoseph Koshy  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24f263522aSJoseph Koshy  * SUCH DAMAGE.
25f263522aSJoseph Koshy  */
26f263522aSJoseph Koshy 
27f263522aSJoseph Koshy #include <sys/cdefs.h>
28f263522aSJoseph Koshy __FBSDID("$FreeBSD$");
29f263522aSJoseph Koshy 
30f263522aSJoseph Koshy #include <sys/param.h>
31f263522aSJoseph Koshy #include <sys/bus.h>
32f263522aSJoseph Koshy #include <sys/pmc.h>
33f263522aSJoseph Koshy #include <sys/systm.h>
34f263522aSJoseph Koshy 
35f263522aSJoseph Koshy #include <machine/apicreg.h>
36f263522aSJoseph Koshy #include <machine/pmc_mdep.h>
37f263522aSJoseph Koshy #include <machine/md_var.h>
38f263522aSJoseph Koshy 
39f263522aSJoseph Koshy extern volatile lapic_t *lapic;
40f263522aSJoseph Koshy 
41f263522aSJoseph Koshy void
42f263522aSJoseph Koshy pmc_x86_lapic_enable_pmc_interrupt(void)
43f263522aSJoseph Koshy {
44f263522aSJoseph Koshy 	uint32_t value;
45f263522aSJoseph Koshy 
46f263522aSJoseph Koshy 	value =  lapic->lvt_pcint;
47f263522aSJoseph Koshy 	value &= ~APIC_LVT_M;
48f263522aSJoseph Koshy 	lapic->lvt_pcint = value;
49f263522aSJoseph Koshy }
50f263522aSJoseph Koshy 
51f263522aSJoseph Koshy 
52f263522aSJoseph Koshy static struct pmc_mdep *
53f263522aSJoseph Koshy pmc_intel_initialize(void)
54f263522aSJoseph Koshy {
55f263522aSJoseph Koshy 	struct pmc_mdep *pmc_mdep;
56f263522aSJoseph Koshy 	enum pmc_cputype cputype;
57f263522aSJoseph Koshy 	int error, model;
58f263522aSJoseph Koshy 
59f263522aSJoseph Koshy 	KASSERT(strcmp(cpu_vendor, "GenuineIntel") == 0,
60f263522aSJoseph Koshy 	    ("[intel,%d] Initializing non-intel processor", __LINE__));
61f263522aSJoseph Koshy 
62f263522aSJoseph Koshy 	PMCDBG(MDP,INI,0, "intel-initialize cpuid=0x%x", cpu_id);
63f263522aSJoseph Koshy 
64f263522aSJoseph Koshy 	cputype = -1;
65f263522aSJoseph Koshy 
66f263522aSJoseph Koshy 	switch (cpu_id & 0xF00) {
67f263522aSJoseph Koshy #if	defined(__i386__)
68f263522aSJoseph Koshy 	case 0x500:		/* Pentium family processors */
69f263522aSJoseph Koshy 		cputype = PMC_CPU_INTEL_P5;
70f263522aSJoseph Koshy 		break;
71f263522aSJoseph Koshy 	case 0x600:		/* Pentium Pro, Celeron, Pentium II & III */
72f263522aSJoseph Koshy 		switch ((cpu_id & 0xF0) >> 4) { /* model number field */
73f263522aSJoseph Koshy 		case 0x1:
74f263522aSJoseph Koshy 			cputype = PMC_CPU_INTEL_P6;
75f263522aSJoseph Koshy 			break;
76f263522aSJoseph Koshy 		case 0x3: case 0x5:
77f263522aSJoseph Koshy 			cputype = PMC_CPU_INTEL_PII;
78f263522aSJoseph Koshy 			break;
79f263522aSJoseph Koshy 		case 0x6:
80f263522aSJoseph Koshy 			cputype = PMC_CPU_INTEL_CL;
81f263522aSJoseph Koshy 			break;
82f263522aSJoseph Koshy 		case 0x7: case 0x8: case 0xA: case 0xB:
83f263522aSJoseph Koshy 			cputype = PMC_CPU_INTEL_PIII;
84f263522aSJoseph Koshy 			break;
85f263522aSJoseph Koshy 		case 0x9: case 0xD:
86f263522aSJoseph Koshy 			cputype = PMC_CPU_INTEL_PM;
87f263522aSJoseph Koshy 			break;
88f263522aSJoseph Koshy 		}
89f263522aSJoseph Koshy 		break;
90f263522aSJoseph Koshy #endif
91f263522aSJoseph Koshy #if	defined(__i386__) || defined(__amd64__)
92f263522aSJoseph Koshy 	case 0xF00:		/* P4 */
93f263522aSJoseph Koshy 		model = ((cpu_id & 0xF0000) >> 12) | ((cpu_id & 0xF0) >> 4);
94f263522aSJoseph Koshy 		if (model >= 0 && model <= 3) /* known models */
95f263522aSJoseph Koshy 			cputype = PMC_CPU_INTEL_PIV;
96f263522aSJoseph Koshy 		break;
97f263522aSJoseph Koshy 	}
98f263522aSJoseph Koshy #endif
99f263522aSJoseph Koshy 
100f263522aSJoseph Koshy 	if ((int) cputype == -1) {
101f263522aSJoseph Koshy 		printf("pmc: Unknown Intel CPU.\n");
102f263522aSJoseph Koshy 		return NULL;
103f263522aSJoseph Koshy 	}
104f263522aSJoseph Koshy 
105f263522aSJoseph Koshy 	MALLOC(pmc_mdep, struct pmc_mdep *, sizeof(struct pmc_mdep),
106f263522aSJoseph Koshy 	    M_PMC, M_WAITOK|M_ZERO);
107f263522aSJoseph Koshy 
108f263522aSJoseph Koshy 	pmc_mdep->pmd_cputype 	    = cputype;
109f263522aSJoseph Koshy 	pmc_mdep->pmd_nclass	    = 2;
110f263522aSJoseph Koshy 	pmc_mdep->pmd_classes[0].pm_class    = PMC_CLASS_TSC;
111f263522aSJoseph Koshy 	pmc_mdep->pmd_classes[0].pm_caps     = PMC_CAP_READ;
112f263522aSJoseph Koshy 	pmc_mdep->pmd_classes[0].pm_width    = 64;
113f263522aSJoseph Koshy 	pmc_mdep->pmd_nclasspmcs[0] = 1;
114f263522aSJoseph Koshy 
115f263522aSJoseph Koshy 	error = 0;
116f263522aSJoseph Koshy 
117f263522aSJoseph Koshy 	switch (cputype) {
118f263522aSJoseph Koshy 
119f263522aSJoseph Koshy #if	defined(__i386__) || defined(__amd64__)
120f263522aSJoseph Koshy 
121f263522aSJoseph Koshy 		/*
122f263522aSJoseph Koshy 		 * Intel Pentium 4 Processors, and P4/EMT64 processors.
123f263522aSJoseph Koshy 		 */
124f263522aSJoseph Koshy 
125f263522aSJoseph Koshy 	case PMC_CPU_INTEL_PIV:
126f263522aSJoseph Koshy 		error = pmc_initialize_p4(pmc_mdep);
127f263522aSJoseph Koshy 		break;
128f263522aSJoseph Koshy #endif
129f263522aSJoseph Koshy 
130f263522aSJoseph Koshy #if	defined(__i386__)
131f263522aSJoseph Koshy 		/*
132f263522aSJoseph Koshy 		 * P6 Family Processors
133f263522aSJoseph Koshy 		 */
134f263522aSJoseph Koshy 
135f263522aSJoseph Koshy 	case PMC_CPU_INTEL_P6:
136f263522aSJoseph Koshy 	case PMC_CPU_INTEL_CL:
137f263522aSJoseph Koshy 	case PMC_CPU_INTEL_PII:
138f263522aSJoseph Koshy 	case PMC_CPU_INTEL_PIII:
139f263522aSJoseph Koshy 	case PMC_CPU_INTEL_PM:
140f263522aSJoseph Koshy 
141f263522aSJoseph Koshy 		error = pmc_initialize_p6(pmc_mdep);
142f263522aSJoseph Koshy 		break;
143f263522aSJoseph Koshy 
144f263522aSJoseph Koshy 		/*
145f263522aSJoseph Koshy 		 * Intel Pentium PMCs.
146f263522aSJoseph Koshy 		 */
147f263522aSJoseph Koshy 
148f263522aSJoseph Koshy 	case PMC_CPU_INTEL_P5:
149f263522aSJoseph Koshy 		error = pmc_initialize_p5(pmc_mdep);
150f263522aSJoseph Koshy 		break;
151f263522aSJoseph Koshy #endif
152f263522aSJoseph Koshy 
153f263522aSJoseph Koshy 	default:
154f263522aSJoseph Koshy 		KASSERT(0,("[intel,%d] Unknown CPU type", __LINE__));
155f263522aSJoseph Koshy 	}
156f263522aSJoseph Koshy 
157f263522aSJoseph Koshy 	if (error) {
158f263522aSJoseph Koshy 		FREE(pmc_mdep, M_PMC);
159f263522aSJoseph Koshy 		pmc_mdep = NULL;
160f263522aSJoseph Koshy 	}
161f263522aSJoseph Koshy 
162f263522aSJoseph Koshy 	return pmc_mdep;
163f263522aSJoseph Koshy }
164f263522aSJoseph Koshy 
165f263522aSJoseph Koshy 
166f263522aSJoseph Koshy /*
167f263522aSJoseph Koshy  * Machine dependent initialization for x86 class platforms.
168f263522aSJoseph Koshy  */
169f263522aSJoseph Koshy 
170f263522aSJoseph Koshy struct pmc_mdep *
171f263522aSJoseph Koshy pmc_md_initialize()
172f263522aSJoseph Koshy {
173f263522aSJoseph Koshy 	/* determine the CPU kind */
174f263522aSJoseph Koshy 	if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
175f263522aSJoseph Koshy 		return pmc_amd_initialize();
176f263522aSJoseph Koshy 	else if (strcmp(cpu_vendor, "GenuineIntel") == 0)
177f263522aSJoseph Koshy 		return pmc_intel_initialize();
178f263522aSJoseph Koshy 	return NULL;
179f263522aSJoseph Koshy }
180