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