xref: /illumos-gate/usr/src/uts/i86pc/cpu/amd_opteron/ao_main.c (revision a07094369b21309434206d9b3601d162693466fc)
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