xref: /netbsd-src/sys/arch/ia64/ia64/cpu.c (revision 02991323a4c6327cf82e06cbf1e20d61b5c66424)
1 /*	$NetBSD: cpu.c,v 1.16 2019/10/01 18:00:07 chs Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  *
8  * Author:
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.16 2019/10/01 18:00:07 chs Exp $");
34 
35 #include <sys/param.h>
36 #include <sys/cpu.h>
37 #include <sys/proc.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 #include <sys/kmem.h>
41 
42 #include <dev/acpi/acpica.h>
43 #include <dev/acpi/acpivar.h>
44 
45 #define MHz	1000000L
46 #define GHz	(1000L * MHz)
47 
48 extern int ia64_sync_icache_needed;
49 
50 struct cpu_info cpu_info_primary __aligned(CACHE_LINE_SIZE);
51 struct cpu_info *cpu_info_list = &cpu_info_primary;
52 
53 struct cpu_softc {
54 	device_t sc_dev;		/* device tree glue */
55 	struct cpu_info *sc_info;	/* pointer to CPU info */
56 };
57 
58 static int cpu_match(device_t, cfdata_t, void *);
59 static void cpu_attach(device_t, device_t, void *);
60 
61 static void identifycpu(struct cpu_softc *);
62 
63 CFATTACH_DECL_NEW(cpu, sizeof(struct cpu_softc),
64     cpu_match, cpu_attach, NULL, NULL);
65 
66 
67 static int
cpu_match(device_t parent,cfdata_t match,void * aux)68 cpu_match(device_t parent, cfdata_t match, void *aux)
69 {
70 
71 	return 1;
72 }
73 
74 static void
cpu_attach(device_t parent,device_t self,void * aux)75 cpu_attach(device_t parent, device_t self, void *aux)
76 {
77 	struct cpu_softc *sc = device_private(self);
78 	ACPI_MADT_LOCAL_SAPIC *sapic = (ACPI_MADT_LOCAL_SAPIC *)aux;
79 	struct cpu_info *ci;
80 	uint64_t lid;
81 	int id, eid;
82 
83 	aprint_naive("\n");
84 	aprint_normal(": ProcessorID %d, Id %d, Eid %d%s\n",
85 	    sapic->ProcessorId, sapic->Id, sapic->Eid,
86 	    sapic->LapicFlags & ACPI_MADT_ENABLED ? "" : " (disabled)");
87 
88 	/* Get current CPU Id */
89 	lid = ia64_get_lid();
90 	id = (lid & 0x00000000ff000000) >> 24;
91 	eid = (lid & 0x0000000000ff0000) >> 16;
92 
93 	sc->sc_dev = self;
94 	if (id == sapic->Id && eid == sapic->Eid)
95 		ci = curcpu();
96 	else {
97 		ci = (struct cpu_info *)kmem_zalloc(sizeof(*ci), KM_SLEEP);
98 	}
99 	sc->sc_info = ci;
100 
101 	ci->ci_cpuid = sapic->ProcessorId;
102 	ci->ci_intrdepth = -1;			/* need ? */
103 	ci->ci_dev = self;
104 
105 	identifycpu(sc);
106 
107 	return;
108 }
109 
110 
111 static void
identifycpu(struct cpu_softc * sc)112 identifycpu(struct cpu_softc *sc)
113 {
114 	uint64_t vendor[3];
115 	const char *family_name, *model_name;
116 	uint64_t features, tmp;
117 	int revision, model, family;
118 	char bitbuf[32];
119 	extern uint64_t processor_frequency;
120 
121 	/*
122 	 * Assumes little-endian.
123 	 */
124 	vendor[0] = ia64_get_cpuid(0);
125 	vendor[1] = ia64_get_cpuid(1);
126 	vendor[2] = '\0';
127 
128 	tmp = ia64_get_cpuid(3);
129 	/* number = (tmp >> 0) & 0xff; */
130 	revision = (tmp >> 8) & 0xff;
131 	model = (tmp >> 16) & 0xff;
132 	family = (tmp >> 24) & 0xff;
133 	/* archrev = (tmp >> 32) & 0xff; */
134 
135 	family_name = model_name = "unknown";
136 	switch (family) {
137 	case 0x07:
138 		family_name = "Itanium";
139 		model_name = "Merced";
140 		break;
141 	case 0x1f:
142 		family_name = "Itanium 2";
143 		switch (model) {
144 		case 0x00:
145 			model_name = "McKinley";
146 			break;
147 		case 0x01:
148 			/*
149 			 * Deerfield is a low-voltage variant based on the
150 			 * Madison core. We need circumstantial evidence
151 			 * (i.e. the clock frequency) to identify those.
152 			 * Allow for roughly 1% error margin.
153 			 */
154 			tmp = processor_frequency >> 7;
155 			if ((processor_frequency - tmp) < 1*GHz &&
156 			    (processor_frequency + tmp) >= 1*GHz)
157 				model_name = "Deerfield";
158 			else
159 				model_name = "Madison";
160 			break;
161 		case 0x02:
162 			model_name = "Madison II";
163 			break;
164 		}
165 		break;
166 	case 0x20:
167 		ia64_sync_icache_needed = 1;
168 
169 		family_name = "Itanium 2";
170 		switch (model) {
171 		case 0x00:
172 			model_name = "Montecito";
173 			break;
174 		case 0x01:
175 			model_name = "Montvale";
176 			break;
177 		}
178 		break;
179 	}
180 	cpu_setmodel("%s", model_name);
181 
182 	features = ia64_get_cpuid(4);
183 
184 	aprint_normal_dev(sc->sc_dev, "%s (", model_name);
185 	if (processor_frequency) {
186 		aprint_normal("%ld.%02ld-MHz ",
187 		    (processor_frequency + 4999) / MHz,
188 		    ((processor_frequency + 4999) / (MHz/100)) % 100);
189 	}
190 	aprint_normal("%s)\n", family_name);
191 	aprint_normal_dev(sc->sc_dev, "Origin \"%s\",  Revision %d\n",
192 	    (char *)vendor, revision);
193 
194 #define IA64_FEATURES_BITMASK "\177\020"				\
195     "b\0LB\0"	/* 'brl' instruction is implemented */			\
196     "b\1SD\0"	/* Processor implements sportaneous deferral */		\
197     "b\2AO\0"	/* Processor implements 16-byte atomic operations */	\
198     "\0"
199 	snprintb(bitbuf, sizeof(bitbuf), IA64_FEATURES_BITMASK, features);
200 	aprint_normal_dev(sc->sc_dev, "Features %s\n", bitbuf);
201 }
202