xref: /netbsd-src/sys/arch/x86/x86/cpu_ucode.c (revision defe44bfc70cfd76ef8dcd678b6e86ba3d7d684c)
1 /* $NetBSD: cpu_ucode.c,v 1.4 2013/07/06 12:03:11 gdt Exp $ */
2 /*
3  * Copyright (c) 2012 The NetBSD Foundation, Inc.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to The NetBSD Foundation
7  * by Christoph Egger.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: cpu_ucode.c,v 1.4 2013/07/06 12:03:11 gdt Exp $");
33 
34 #include "opt_cpu_ucode.h"
35 #include "opt_compat_netbsd.h"
36 
37 #include <sys/param.h>
38 #include <sys/cpuio.h>
39 #include <sys/cpu.h>
40 
41 #include <dev/firmload.h>
42 
43 #include <machine/cpuvar.h>
44 #include <machine/cputypes.h>
45 
46 #include <x86/cpu_ucode.h>
47 
48 static struct cpu_ucode_softc ucode_softc;
49 
50 int
51 cpu_ucode_get_version(struct cpu_ucode_version *data)
52 {
53 
54 	switch (cpu_vendor) {
55 	case CPUVENDOR_AMD:
56 		return cpu_ucode_amd_get_version(data);
57 	case CPUVENDOR_INTEL:
58 		return cpu_ucode_intel_get_version(data);
59 	default:
60 		return EOPNOTSUPP;
61 	}
62 
63 	return 0;
64 }
65 
66 #ifdef COMPAT_60
67 int
68 compat6_cpu_ucode_get_version(struct compat6_cpu_ucode *data)
69 {
70 
71 	switch (cpu_vendor) {
72 	case CPUVENDOR_AMD:
73 		return compat6_cpu_ucode_amd_get_version(data);
74 	default:
75 		return EOPNOTSUPP;
76 	}
77 
78 	return 0;
79 }
80 #endif /* COMPAT60 */
81 
82 int
83 cpu_ucode_md_open(firmware_handle_t *fwh, int loader_version, const char *fwname)
84 {
85 	switch (cpu_vendor) {
86 	case CPUVENDOR_AMD:
87 		return cpu_ucode_amd_firmware_open(fwh, fwname);
88 	case CPUVENDOR_INTEL:
89 		return cpu_ucode_intel_firmware_open(fwh, fwname);
90 	default:
91 		return EOPNOTSUPP;
92 	}
93 }
94 
95 int
96 cpu_ucode_apply(const struct cpu_ucode *data)
97 {
98 	struct cpu_ucode_softc *sc = &ucode_softc;
99 	int error;
100 
101 	sc->loader_version = data->loader_version;
102 
103 	error = cpu_ucode_load(sc, data->fwname);
104 	if (error)
105 		return error;
106 
107 	switch (cpu_vendor) {
108 	case CPUVENDOR_AMD:
109 		error = cpu_ucode_amd_apply(sc, data->cpu_nr);
110 		break;
111 	case CPUVENDOR_INTEL:
112 		error = cpu_ucode_intel_apply(sc, data->cpu_nr);
113 		break;
114 	default:
115 		return EOPNOTSUPP;
116 	}
117 
118 	if (sc->sc_blob != NULL)
119 		firmware_free(sc->sc_blob, 0);
120 	sc->sc_blob = NULL;
121 	sc->sc_blobsize = 0;
122 	return error;
123 }
124 
125 #ifdef COMPAT_60
126 int
127 compat6_cpu_ucode_apply(const struct compat6_cpu_ucode *data)
128 {
129 	struct cpu_ucode_softc *sc = &ucode_softc;
130 	int error;
131 
132 	if (cpu_vendor != CPUVENDOR_AMD)
133 		return EOPNOTSUPP;
134 
135 	sc->loader_version = CPU_UCODE_LOADER_AMD;
136 	error = cpu_ucode_load(sc, data->fwname);
137 	if (error)
138 		return error;
139 
140 	error = cpu_ucode_amd_apply(sc, CPU_UCODE_ALL_CPUS);
141 
142 	if (sc->sc_blob != NULL)
143 		firmware_free(sc->sc_blob, 0);
144 	sc->sc_blob = NULL;
145 	sc->sc_blobsize = 0;
146 	return error;
147 }
148 #endif /* COMPAT60 */
149