1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 /* 31 * The CPU module for the AMD Athlon64 and Opteron processors 32 */ 33 34 #include <sys/types.h> 35 #include <sys/cmn_err.h> 36 #include <sys/sunddi.h> 37 #include <sys/cpu_module_impl.h> 38 #include <sys/cpuvar.h> 39 #include <sys/x86_archext.h> 40 #include <sys/kmem.h> 41 #include <sys/modctl.h> 42 #include <sys/mc.h> 43 44 #include "ao.h" 45 46 /* 47 * At present this CPU module only supports the features for Athlon64 and 48 * Opteron up to and including the Rev E processor. If we detect Rev F or 49 * later, return ENOTSUP and let the generic x86 CPU module load instead. 50 * Opteron Rev F is currently defined as Family 0xF Model [0x40 .. 0x5F]. 51 */ 52 static uint_t ao_model_limit = 0x40; 53 54 static int 55 ao_init(cpu_t *cp, void **datap) 56 { 57 ao_data_t *ao; 58 59 if (cpuid_getmodel(cp) >= ao_model_limit) 60 return (ENOTSUP); 61 62 ao = *datap = kmem_zalloc(sizeof (ao_data_t), KM_SLEEP); 63 ao->ao_cpu = cp; 64 65 return (0); 66 } 67 68 static void 69 ao_fini(void *data) 70 { 71 kmem_free(data, sizeof (ao_data_t)); 72 } 73 74 const cmi_ops_t _cmi_ops = { 75 ao_init, 76 ao_mca_post_init, 77 ao_fini, 78 ao_faulted_enter, 79 ao_faulted_exit, 80 ao_scrubber_enable, 81 ao_mca_init, 82 ao_mca_trap, 83 ao_mca_inject, 84 ao_mca_poke, 85 ao_mc_register, 86 ao_mc_getops 87 }; 88 89 static struct modlcpu modlcpu = { 90 &mod_cpuops, 91 "AMD Athlon64/Opteron CPU Module" 92 }; 93 94 static struct modlinkage modlinkage = { 95 MODREV_1, 96 (void *)&modlcpu, 97 NULL 98 }; 99 100 int 101 _init(void) 102 { 103 int err; 104 105 ao_mca_queue = errorq_create("ao_mca_queue", 106 ao_mca_drain, NULL, AO_MCA_MAX_ERRORS * (max_ncpus + 1), 107 sizeof (ao_cpu_logout_t), 1, ERRORQ_VITAL); 108 109 if (ao_mca_queue == NULL) 110 return (EAGAIN); /* errorq_create() logs a message for us */ 111 112 if ((err = mod_install(&modlinkage)) != 0) { 113 errorq_destroy(ao_mca_queue); 114 ao_mca_queue = NULL; 115 } 116 117 return (err); 118 } 119 120 int 121 _info(struct modinfo *modinfop) 122 { 123 return (mod_info(&modlinkage, modinfop)); 124 } 125 126 int 127 _fini(void) 128 { 129 int err; 130 131 if ((err = mod_remove(&modlinkage)) == 0) 132 errorq_destroy(ao_mca_queue); 133 134 return (err); 135 } 136