Module Name: src
Committed By: cegger
Date: Fri Jan 13 16:05:16 UTC 2012
Modified Files:
src/share/man/man4: options.4
src/sys/arch/amd64/conf: GENERIC XEN3_DOM0
src/sys/arch/i386/conf: GENERIC XEN3_DOM0
src/sys/arch/x86/conf: files.x86
src/sys/arch/xen/conf: files.xen
src/sys/kern: kern_cpu.c
src/sys/secmodel/securelevel: secmodel_securelevel.c
src/sys/secmodel/suser: secmodel_suser.c
src/sys/sys: cpu.h cpuio.h kauth.h
src/usr.sbin/cpuctl: cpuctl.8 cpuctl.c
Added Files:
src/sys/arch/x86/include: cpu_ucode.h
src/sys/arch/x86/x86: cpu_ucode.c cpu_ucode_amd.c
src/sys/arch/xen/xen: xen_ucode.c
Log Message:
Support CPU microcode loading via cpuctl(8).
Implemented and enabled via CPU_UCODE kernel config option
for x86 and Xen Dom0.
Tested on different AMD machines with different
CPU families.
ok wiz@ for the manpages
ok releng@
ok core@ via releng@
To generate a diff of this commit:
cvs rdiff -u -r1.410 -r1.411 src/share/man/man4/options.4
cvs rdiff -u -r1.342 -r1.343 src/sys/arch/amd64/conf/GENERIC
cvs rdiff -u -r1.76 -r1.77 src/sys/arch/amd64/conf/XEN3_DOM0
cvs rdiff -u -r1.1061 -r1.1062 src/sys/arch/i386/conf/GENERIC
cvs rdiff -u -r1.58 -r1.59 src/sys/arch/i386/conf/XEN3_DOM0
cvs rdiff -u -r1.75 -r1.76 src/sys/arch/x86/conf/files.x86
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/include/cpu_ucode.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/x86/cpu_ucode.c \
src/sys/arch/x86/x86/cpu_ucode_amd.c
cvs rdiff -u -r1.123 -r1.124 src/sys/arch/xen/conf/files.xen
cvs rdiff -u -r0 -r1.1 src/sys/arch/xen/xen/xen_ucode.c
cvs rdiff -u -r1.52 -r1.53 src/sys/kern/kern_cpu.c
cvs rdiff -u -r1.24 -r1.25 \
src/sys/secmodel/securelevel/secmodel_securelevel.c
cvs rdiff -u -r1.36 -r1.37 src/sys/secmodel/suser/secmodel_suser.c
cvs rdiff -u -r1.33 -r1.34 src/sys/sys/cpu.h
cvs rdiff -u -r1.5 -r1.6 src/sys/sys/cpuio.h
cvs rdiff -u -r1.66 -r1.67 src/sys/sys/kauth.h
cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/cpuctl/cpuctl.8
cvs rdiff -u -r1.19 -r1.20 src/usr.sbin/cpuctl/cpuctl.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/share/man/man4/options.4
diff -u src/share/man/man4/options.4:1.410 src/share/man/man4/options.4:1.411
--- src/share/man/man4/options.4:1.410 Mon Jan 9 15:16:31 2012
+++ src/share/man/man4/options.4 Fri Jan 13 16:05:16 2012
@@ -1,4 +1,4 @@
-.\" $NetBSD: options.4,v 1.410 2012/01/09 15:16:31 drochner Exp $
+.\" $NetBSD: options.4,v 1.411 2012/01/13 16:05:16 cegger Exp $
.\"
.\" Copyright (c) 1996
.\" Perry E. Metzger. All rights reserved.
@@ -30,7 +30,7 @@
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\"
-.Dd January 9, 2012
+.Dd January 13, 2012
.Dt OPTIONS 4
.Os
.Sh NAME
@@ -1093,6 +1093,9 @@ Synonym of
.El
.Ss Miscellaneous Options
.Bl -ohang
+.It Cd options CPU_UCODE
+Support cpu microcode loading via
+.Xr cpuctl 8 .
.It Cd options MEMORY_DISK_DYNAMIC
This option makes the
.Xr md 4
Index: src/sys/arch/amd64/conf/GENERIC
diff -u src/sys/arch/amd64/conf/GENERIC:1.342 src/sys/arch/amd64/conf/GENERIC:1.343
--- src/sys/arch/amd64/conf/GENERIC:1.342 Sat Dec 31 00:10:06 2011
+++ src/sys/arch/amd64/conf/GENERIC Fri Jan 13 16:05:14 2012
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.342 2011/12/31 00:10:06 christos Exp $
+# $NetBSD: GENERIC,v 1.343 2012/01/13 16:05:14 cegger Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.342 $"
+#ident "GENERIC-$Revision: 1.343 $"
maxusers 64 # estimated number of users
@@ -60,6 +60,8 @@ options NTP # NTP phase/frequency lock
options KTRACE # system call tracing via ktrace(1)
+options CPU_UCODE # cpu ucode loading support
+
# Note: SysV IPC parameters could be changed dynamically, see sysctl(8).
options SYSVMSG # System V-like message queues
options SYSVSEM # System V-like semaphores
Index: src/sys/arch/amd64/conf/XEN3_DOM0
diff -u src/sys/arch/amd64/conf/XEN3_DOM0:1.76 src/sys/arch/amd64/conf/XEN3_DOM0:1.77
--- src/sys/arch/amd64/conf/XEN3_DOM0:1.76 Sun Dec 18 05:49:23 2011
+++ src/sys/arch/amd64/conf/XEN3_DOM0 Fri Jan 13 16:05:14 2012
@@ -1,4 +1,4 @@
-# $NetBSD: XEN3_DOM0,v 1.76 2011/12/18 05:49:23 dholland Exp $
+# $NetBSD: XEN3_DOM0,v 1.77 2012/01/13 16:05:14 cegger Exp $
include "arch/amd64/conf/std.xen"
@@ -35,6 +35,8 @@ options NTP # NTP phase/frequency lock
options KTRACE # system call tracing via ktrace(1)
+options CPU_UCODE # cpu ucode loading support
+
options SYSVMSG # System V-like message queues
options SYSVSEM # System V-like semaphores
options SYSVSHM # System V-like memory sharing
Index: src/sys/arch/i386/conf/GENERIC
diff -u src/sys/arch/i386/conf/GENERIC:1.1061 src/sys/arch/i386/conf/GENERIC:1.1062
--- src/sys/arch/i386/conf/GENERIC:1.1061 Sat Dec 31 00:11:21 2011
+++ src/sys/arch/i386/conf/GENERIC Fri Jan 13 16:05:14 2012
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.1061 2011/12/31 00:11:21 christos Exp $
+# $NetBSD: GENERIC,v 1.1062 2012/01/13 16:05:14 cegger Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.1061 $"
+#ident "GENERIC-$Revision: 1.1062 $"
maxusers 64 # estimated number of users
@@ -80,6 +80,8 @@ options NTP # NTP phase/frequency lock
options KTRACE # system call tracing via ktrace(1)
+options CPU_UCODE # cpu ucode loading support
+
# Note: SysV IPC parameters can be changed dynamically; see sysctl(8).
options SYSVMSG # System V-like message queues
options SYSVSEM # System V-like semaphores
Index: src/sys/arch/i386/conf/XEN3_DOM0
diff -u src/sys/arch/i386/conf/XEN3_DOM0:1.58 src/sys/arch/i386/conf/XEN3_DOM0:1.59
--- src/sys/arch/i386/conf/XEN3_DOM0:1.58 Sun Dec 18 05:49:28 2011
+++ src/sys/arch/i386/conf/XEN3_DOM0 Fri Jan 13 16:05:14 2012
@@ -1,4 +1,4 @@
-# $NetBSD: XEN3_DOM0,v 1.58 2011/12/18 05:49:28 dholland Exp $
+# $NetBSD: XEN3_DOM0,v 1.59 2012/01/13 16:05:14 cegger Exp $
#
# XEN3_0: Xen 3.0 domain0 kernel
@@ -45,6 +45,8 @@ options NTP # NTP phase/frequency lock
options KTRACE # system call tracing via ktrace(1)
+options CPU_UCODE # cpu ucode loading support
+
options SYSVMSG # System V-like message queues
options SYSVSEM # System V-like semaphores
#options SEMMNI=10 # number of semaphore identifiers
Index: src/sys/arch/x86/conf/files.x86
diff -u src/sys/arch/x86/conf/files.x86:1.75 src/sys/arch/x86/conf/files.x86:1.76
--- src/sys/arch/x86/conf/files.x86:1.75 Wed Oct 19 05:22:25 2011
+++ src/sys/arch/x86/conf/files.x86 Fri Jan 13 16:05:14 2012
@@ -1,4 +1,4 @@
-# $NetBSD: files.x86,v 1.75 2011/10/19 05:22:25 dyoung Exp $
+# $NetBSD: files.x86,v 1.76 2012/01/13 16:05:14 cegger Exp $
# options for MP configuration through the MP spec
defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
@@ -93,6 +93,10 @@ file arch/x86/x86/x86_autoconf.c
file arch/x86/x86/x86_userconf.c userconf
file arch/x86/x86/x86_machdep.c
+defflag CPU_UCODE
+file arch/x86/x86/cpu_ucode.c cpu_ucode needs-flag
+file arch/x86/x86/cpu_ucode_amd.c cpu_ucode needs-flag
+
define lapic
file arch/x86/x86/lapic.c lapic needs-flag
Index: src/sys/arch/xen/conf/files.xen
diff -u src/sys/arch/xen/conf/files.xen:1.123 src/sys/arch/xen/conf/files.xen:1.124
--- src/sys/arch/xen/conf/files.xen:1.123 Thu Sep 22 23:02:34 2011
+++ src/sys/arch/xen/conf/files.xen Fri Jan 13 16:05:15 2012
@@ -1,4 +1,4 @@
-# $NetBSD: files.xen,v 1.123 2011/09/22 23:02:34 jym Exp $
+# $NetBSD: files.xen,v 1.124 2012/01/13 16:05:15 cegger Exp $
# NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp
# NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp
@@ -93,6 +93,10 @@ file arch/xen/x86/xen_pmap.c
file arch/xen/x86/xen_intr.c
file arch/xen/x86/xenfunc.c
+defflag CPU_UCODE
+file arch/xen/xen/xen_ucode.c dom0ops | cpu_ucode needs-flag
+file arch/x86/x86/cpu_ucode_amd.c dom0ops | cpu_ucode needs-flag
+
file arch/xen/xen/xen_machdep.c
file arch/xen/xen/xen_debug.c
Index: src/sys/kern/kern_cpu.c
diff -u src/sys/kern/kern_cpu.c:1.52 src/sys/kern/kern_cpu.c:1.53
--- src/sys/kern/kern_cpu.c:1.52 Sat Oct 29 11:41:32 2011
+++ src/sys/kern/kern_cpu.c Fri Jan 13 16:05:15 2012
@@ -1,7 +1,7 @@
-/* $NetBSD: kern_cpu.c,v 1.52 2011/10/29 11:41:32 jym Exp $ */
+/* $NetBSD: kern_cpu.c,v 1.53 2012/01/13 16:05:15 cegger Exp $ */
/*-
- * Copyright (c) 2007, 2008, 2009, 2010 The NetBSD Foundation, Inc.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -56,7 +56,9 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.52 2011/10/29 11:41:32 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.53 2012/01/13 16:05:15 cegger Exp $");
+
+#include "opt_cpu_ucode.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -245,6 +247,26 @@ cpuctl_ioctl(dev_t dev, u_long cmd, void
*(int *)data = ncpu;
break;
+#ifdef CPU_UCODE
+ case IOC_CPU_UCODE_GET_VERSION:
+ error = cpu_ucode_get_version(data);
+ break;
+
+ case IOC_CPU_UCODE_APPLY:
+ error = kauth_authorize_machdep(l->l_cred,
+ KAUTH_MACHDEP_CPU_UCODE_APPLY,
+ NULL, NULL, NULL, NULL);
+ if (error != 0)
+ break;
+ error = kauth_authorize_system(l->l_cred,
+ KAUTH_SYSTEM_CPU, KAUTH_REQ_SYSTEM_CPU_UCODE_APPLY,
+ data, NULL, NULL);
+ if (error != 0)
+ break;
+ error = cpu_ucode_apply(data);
+ break;
+#endif
+
default:
error = ENOTTY;
break;
@@ -507,3 +529,46 @@ cpu_softintr_p(void)
return (curlwp->l_pflag & LP_INTR) != 0;
}
+
+#ifdef CPU_UCODE
+int
+cpu_ucode_load(struct cpu_ucode_softc *sc, const char *fwname)
+{
+ firmware_handle_t fwh;
+ int error;
+
+ if (sc->sc_blob != NULL) {
+ firmware_free(sc->sc_blob, 0);
+ sc->sc_blob = NULL;
+ sc->sc_blobsize = 0;
+ }
+
+ error = cpu_ucode_md_open(&fwh, fwname);
+ if (error != 0) {
+ aprint_error("ucode: firmware_open failed: %i\n", error);
+ goto err0;
+ }
+
+ sc->sc_blobsize = firmware_get_size(fwh);
+ sc->sc_blob = firmware_malloc(sc->sc_blobsize);
+ if (sc->sc_blob == NULL) {
+ error = ENOMEM;
+ firmware_close(fwh);
+ goto err0;
+ }
+
+ error = firmware_read(fwh, 0, sc->sc_blob, sc->sc_blobsize);
+ firmware_close(fwh);
+ if (error != 0)
+ goto err1;
+
+ return 0;
+
+err1:
+ firmware_free(sc->sc_blob, 0);
+ sc->sc_blob = NULL;
+ sc->sc_blobsize = 0;
+err0:
+ return error;
+}
+#endif
Index: src/sys/secmodel/securelevel/secmodel_securelevel.c
diff -u src/sys/secmodel/securelevel/secmodel_securelevel.c:1.24 src/sys/secmodel/securelevel/secmodel_securelevel.c:1.25
--- src/sys/secmodel/securelevel/secmodel_securelevel.c:1.24 Mon Dec 5 00:13:30 2011
+++ src/sys/secmodel/securelevel/secmodel_securelevel.c Fri Jan 13 16:05:15 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_securelevel.c,v 1.24 2011/12/05 00:13:30 jym Exp $ */
+/* $NetBSD: secmodel_securelevel.c,v 1.25 2012/01/13 16:05:15 cegger Exp $ */
/*-
* Copyright (c) 2006 Elad Efrat <[email protected]>
* All rights reserved.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.24 2011/12/05 00:13:30 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.25 2012/01/13 16:05:15 cegger Exp $");
#ifdef _KERNEL_OPT
#include "opt_insecure.h"
@@ -483,6 +483,11 @@ secmodel_securelevel_machdep_cb(kauth_cr
result = KAUTH_RESULT_DENY;
break;
+ case KAUTH_MACHDEP_CPU_UCODE_APPLY:
+ if (securelevel < 1)
+ result = KAUTH_RESULT_ALLOW;
+ break;
+
default:
break;
}
Index: src/sys/secmodel/suser/secmodel_suser.c
diff -u src/sys/secmodel/suser/secmodel_suser.c:1.36 src/sys/secmodel/suser/secmodel_suser.c:1.37
--- src/sys/secmodel/suser/secmodel_suser.c:1.36 Sun Dec 4 19:25:01 2011
+++ src/sys/secmodel/suser/secmodel_suser.c Fri Jan 13 16:05:15 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_suser.c,v 1.36 2011/12/04 19:25:01 jym Exp $ */
+/* $NetBSD: secmodel_suser.c,v 1.37 2012/01/13 16:05:15 cegger Exp $ */
/*-
* Copyright (c) 2006 Elad Efrat <[email protected]>
* All rights reserved.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.36 2011/12/04 19:25:01 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.37 2012/01/13 16:05:15 cegger Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -248,6 +248,7 @@ secmodel_suser_system_cb(kauth_cred_t cr
case KAUTH_SYSTEM_CPU:
switch (req) {
case KAUTH_REQ_SYSTEM_CPU_SETSTATE:
+ case KAUTH_REQ_SYSTEM_CPU_UCODE_APPLY:
if (isroot)
result = KAUTH_RESULT_ALLOW;
Index: src/sys/sys/cpu.h
diff -u src/sys/sys/cpu.h:1.33 src/sys/sys/cpu.h:1.34
--- src/sys/sys/cpu.h:1.33 Sun Aug 7 13:33:02 2011
+++ src/sys/sys/cpu.h Fri Jan 13 16:05:16 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.33 2011/08/07 13:33:02 rmind Exp $ */
+/* $NetBSD: cpu.h,v 1.34 2012/01/13 16:05:16 cegger Exp $ */
/*-
* Copyright (c) 2007 YAMAMOTO Takashi,
@@ -42,6 +42,10 @@ struct cpu_info;
void cpu_idle(void);
#endif
+#ifdef CPU_UCODE
+#include <dev/firmload.h>
+#endif
+
/*
* cpu_need_resched() must always be called with the target CPU
* locked (via spc_lock() or another route), unless called locally.
@@ -102,6 +106,19 @@ cpu_name(struct cpu_info *ci)
{
return ci->ci_data.cpu_name;
}
+
+#ifdef CPU_UCODE
+struct cpu_ucode_softc {
+ char *sc_blob;
+ off_t sc_blobsize;
+};
+
+int cpu_ucode_get_version(void *);
+int cpu_ucode_apply(void *);
+int cpu_ucode_load(struct cpu_ucode_softc *, const char *);
+int cpu_ucode_md_open(firmware_handle_t *, const char *);
+#endif
+
#endif
#endif /* !_LOCORE */
Index: src/sys/sys/cpuio.h
diff -u src/sys/sys/cpuio.h:1.5 src/sys/sys/cpuio.h:1.6
--- src/sys/sys/cpuio.h:1.5 Sun Sep 11 14:54:49 2011
+++ src/sys/sys/cpuio.h Fri Jan 13 16:05:16 2012
@@ -1,7 +1,7 @@
-/* $NetBSD: cpuio.h,v 1.5 2011/09/11 14:54:49 jdc Exp $ */
+/* $NetBSD: cpuio.h,v 1.6 2012/01/13 16:05:16 cegger Exp $ */
/*-
- * Copyright (c) 2007, 2009 The NetBSD Foundation, Inc.
+ * Copyright (c) 2007, 2009, 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -62,4 +62,12 @@ typedef struct cpustate {
#define IOC_CPU_GETCOUNT _IOR('c', 2, int)
#define IOC_CPU_MAPID _IOWR('c', 3, int)
+struct cpu_ucode {
+ uint64_t version;
+ char fwname[PATH_MAX];
+};
+
+#define IOC_CPU_UCODE_GET_VERSION _IOR('c', 4, struct cpu_ucode)
+#define IOC_CPU_UCODE_APPLY _IOW('c', 5, struct cpu_ucode)
+
#endif /* !_SYS_CPUIO_H_ */
Index: src/sys/sys/kauth.h
diff -u src/sys/sys/kauth.h:1.66 src/sys/sys/kauth.h:1.67
--- src/sys/sys/kauth.h:1.66 Sun Dec 4 19:25:01 2011
+++ src/sys/sys/kauth.h Fri Jan 13 16:05:16 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: kauth.h,v 1.66 2011/12/04 19:25:01 jym Exp $ */
+/* $NetBSD: kauth.h,v 1.67 2012/01/13 16:05:16 cegger Exp $ */
/*-
* Copyright (c) 2005, 2006 Elad Efrat <[email protected]>
@@ -109,6 +109,7 @@ enum kauth_system_req {
KAUTH_REQ_SYSTEM_CHROOT_CHROOT=1,
KAUTH_REQ_SYSTEM_CHROOT_FCHROOT,
KAUTH_REQ_SYSTEM_CPU_SETSTATE,
+ KAUTH_REQ_SYSTEM_CPU_UCODE_APPLY,
KAUTH_REQ_SYSTEM_DEBUG_IPKDB,
KAUTH_REQ_SYSTEM_MOUNT_GET,
KAUTH_REQ_SYSTEM_MOUNT_NEW,
@@ -235,6 +236,7 @@ enum kauth_network_req {
*/
enum {
KAUTH_MACHDEP_CACHEFLUSH=1,
+ KAUTH_MACHDEP_CPU_UCODE_APPLY,
KAUTH_MACHDEP_IOPERM_GET,
KAUTH_MACHDEP_IOPERM_SET,
KAUTH_MACHDEP_IOPL,
Index: src/usr.sbin/cpuctl/cpuctl.8
diff -u src/usr.sbin/cpuctl/cpuctl.8:1.6 src/usr.sbin/cpuctl/cpuctl.8:1.7
--- src/usr.sbin/cpuctl/cpuctl.8:1.6 Sun Jun 22 14:50:40 2008
+++ src/usr.sbin/cpuctl/cpuctl.8 Fri Jan 13 16:05:16 2012
@@ -1,6 +1,6 @@
-.\" $NetBSD: cpuctl.8,v 1.6 2008/06/22 14:50:40 wiz Exp $
+.\" $NetBSD: cpuctl.8,v 1.7 2012/01/13 16:05:16 cegger Exp $
.\"
-.\" Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
+.\" Copyright (c) 2007, 2008, 2012 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd June 22, 2008
+.Dd January 13, 2012
.Dt CPUCTL 8
.Os
.Sh NAME
@@ -66,11 +66,48 @@ away from individual CPUs.
At least one CPU in the system must remain on line.
.It online Ar cpuno
Set the specified CPU on line, making it available to run unbound LWPs.
+.It ucode Op Ar file
+This applies the microcode patch on all cpus.
+The default filename is used if no filename is specified.
+The
+.Cm identify
+command prints the installed version on that cpu.
+On success the
+.Cm identify
+command show different ucode versions before and after this command.
.El
+.Sh EXAMPLES
+Run
+.Dl cpuctl identify 0
+and you should see something like this:
+.Bd -literal -offset indent
+cpu0: UCode version: 0x1000080
+.Ed
+.Pp
+After applying the microcode patch with
+.Dl cpuctl ucode
+you can see with
+.Dl cpuctl identify 0
+that the patch got applied:
+.Bd -literal -offset indent
+cpu0: UCode version: 0x1000083
+.Ed
.Sh FILES
.Bl -tag -width /dev/cpuctl -compact
.It Pa /dev/cpuctl
control device
+.It Pa /libdata/firmware/x86/amd/
+The directory to install the microcode file for AMD CPUs into.
+The default filename is
+.Pa microcode_amd.bin
+for CPU families 0x10 to 0x14.
+The default filename is
+.Pa microcode_amd_famXXh.bin
+where
+.Dv XX
+is the CPU family starting with 15 (hex).
+Get it from
+.Pa http://www.amd64.org/support/microcode.html
.El
.Sh SEE ALSO
.Xr psrset 8 ,
Index: src/usr.sbin/cpuctl/cpuctl.c
diff -u src/usr.sbin/cpuctl/cpuctl.c:1.19 src/usr.sbin/cpuctl/cpuctl.c:1.20
--- src/usr.sbin/cpuctl/cpuctl.c:1.19 Tue Sep 27 11:24:21 2011
+++ src/usr.sbin/cpuctl/cpuctl.c Fri Jan 13 16:05:16 2012
@@ -1,7 +1,7 @@
-/* $NetBSD: cpuctl.c,v 1.19 2011/09/27 11:24:21 jruoho Exp $ */
+/* $NetBSD: cpuctl.c,v 1.20 2012/01/13 16:05:16 cegger Exp $ */
/*-
- * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
+ * Copyright (c) 2007, 2008, 2009, 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -31,7 +31,7 @@
#ifndef lint
#include <sys/cdefs.h>
-__RCSID("$NetBSD: cpuctl.c,v 1.19 2011/09/27 11:24:21 jruoho Exp $");
+__RCSID("$NetBSD: cpuctl.c,v 1.20 2012/01/13 16:05:16 cegger Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -63,19 +63,22 @@ static void cpu_offline(char **);
static void cpu_online(char **);
static void cpu_intr(char **);
static void cpu_nointr(char **);
+static void cpu_ucode(char **);
static struct cmdtab {
const char *label;
int takesargs;
+ int argsoptional;
void (*func)(char **);
} const cpu_cmdtab[] = {
- { "identify", 1, cpu_identify },
- { "list", 0, cpu_list },
- { "offline", 1, cpu_offline },
- { "online", 1, cpu_online },
- { "intr", 1, cpu_intr },
- { "nointr", 1, cpu_nointr },
- { NULL, 0, NULL },
+ { "identify", 1, 0, cpu_identify },
+ { "list", 0, 0, cpu_list },
+ { "offline", 1, 0, cpu_offline },
+ { "online", 1, 0, cpu_online },
+ { "intr", 1, 0, cpu_intr },
+ { "nointr", 1, 0, cpu_nointr },
+ { "ucode", 1, 1, cpu_ucode },
+ { NULL, 0, 0, NULL },
};
static int fd;
@@ -93,8 +96,11 @@ main(int argc, char **argv)
for (ct = cpu_cmdtab; ct->label != NULL; ct++) {
if (strcmp(argv[1], ct->label) == 0) {
- if ((ct->takesargs == 0) ^ (argv[2] == NULL))
- usage();
+ if (!ct->argsoptional &&
+ ((ct->takesargs == 0) ^ (argv[2] == NULL)))
+ {
+ usage();
+ }
(*ct->func)(argv + 2);
break;
}
@@ -119,6 +125,7 @@ usage(void)
fprintf(stderr, " %s online cpuno\n", progname);
fprintf(stderr, " %s intr cpuno\n", progname);
fprintf(stderr, " %s nointr cpuno\n", progname);
+ fprintf(stderr, " %s ucode [file]\n", progname);
exit(EXIT_FAILURE);
/* NOTREACHED */
}
@@ -181,11 +188,34 @@ cpu_nointr(char **argv)
}
static void
+cpu_ucode(char **argv)
+{
+ int error;
+ struct cpu_ucode uc;
+
+ if (argv[0] != NULL)
+ strlcpy(uc.fwname, argv[0], sizeof(uc.fwname));
+ else
+ memset(uc.fwname, '\0', sizeof(uc.fwname));
+
+ error = ioctl(fd, IOC_CPU_UCODE_APPLY, &uc);
+ if (error < 0) {
+ if (uc.fwname[0])
+ err(EXIT_FAILURE, "%s", uc.fwname);
+ else
+ err(EXIT_FAILURE, "IOC_CPU_UCODE_APPLY");
+ }
+}
+
+
+static void
cpu_identify(char **argv)
{
char name[32];
unsigned int id, np;
cpuset_t *cpuset;
+ struct cpu_ucode ucode;
+ char ucbuf[16];
np = sysconf(_SC_NPROCESSORS_CONF);
id = getcpuid(argv);
@@ -209,6 +239,16 @@ cpu_identify(char **argv)
cpuset_destroy(cpuset);
}
identifycpu(name);
+
+ if (ioctl(fd, IOC_CPU_UCODE_GET_VERSION, &ucode) < 0)
+ ucode.version = (uint64_t)-1;
+ if (ucode.version == (uint64_t)-1)
+ strcpy(ucbuf, "?");
+ else
+ snprintf(ucbuf, sizeof(ucbuf), "0x%"PRIx64,
+ ucode.version);
+
+ printf("%s: UCode version: %s\n", name, ucbuf);
}
static u_int
@@ -263,11 +303,13 @@ cpu_list(char **argv)
strcpy(ibuf, "?");
else
snprintf(ibuf, sizeof(ibuf), "%d", cs.cs_intrcnt - 1);
+
lastmod = (time_t)cs.cs_lastmod |
((time_t)cs.cs_lastmodhi << 32);
ts = asctime(localtime(&lastmod));
ts[strlen(ts) - 1] = '\0';
- printf("%-4d %-4x %-12s %-10s %s %s\n", i, cs.cs_hwid, state,
+ printf("%-4d %-4x %-12s %-10s %s %-5s\n",
+ i, cs.cs_hwid, state,
intr, ts, ibuf);
}
}
Added files:
Index: src/sys/arch/x86/include/cpu_ucode.h
diff -u /dev/null src/sys/arch/x86/include/cpu_ucode.h:1.1
--- /dev/null Fri Jan 13 16:05:16 2012
+++ src/sys/arch/x86/include/cpu_ucode.h Fri Jan 13 16:05:14 2012
@@ -0,0 +1,42 @@
+/* $NetBSD: cpu_ucode.h,v 1.1 2012/01/13 16:05:14 cegger Exp $ */
+/*
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christoph Egger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _X86_CPU_UCODE_H_
+#define _X86_CPU_UCODE_H_
+
+#include <sys/cpu.h>
+#include <sys/cpuio.h>
+#include <dev/firmload.h>
+
+int cpu_ucode_amd_get_version(struct cpu_ucode *);
+int cpu_ucode_amd_firmware_open(firmware_handle_t *, const char *);
+int cpu_ucode_amd_apply(struct cpu_ucode_softc *);
+
+#endif
Index: src/sys/arch/x86/x86/cpu_ucode.c
diff -u /dev/null src/sys/arch/x86/x86/cpu_ucode.c:1.1
--- /dev/null Fri Jan 13 16:05:16 2012
+++ src/sys/arch/x86/x86/cpu_ucode.c Fri Jan 13 16:05:15 2012
@@ -0,0 +1,102 @@
+/* $NetBSD: cpu_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $ */
+/*
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christoph Egger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: cpu_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $");
+
+#include "opt_cpu_ucode.h"
+
+#include <sys/param.h>
+#include <sys/cpuio.h>
+#include <sys/cpu.h>
+
+#include <dev/firmload.h>
+
+#include <machine/cpuvar.h>
+#include <machine/cputypes.h>
+
+#include <x86/cpu_ucode.h>
+
+static struct cpu_ucode_softc ucode_softc;
+
+int
+cpu_ucode_get_version(void *data)
+{
+ struct cpu_ucode *ucode = data;
+
+ switch (cpu_vendor) {
+ case CPUVENDOR_AMD:
+ return cpu_ucode_amd_get_version(ucode);
+ default:
+ ucode->version = (uint64_t)-1;
+ return EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+int
+cpu_ucode_md_open(firmware_handle_t *fwh, const char *fwname)
+{
+ switch (cpu_vendor) {
+ case CPUVENDOR_AMD:
+ return cpu_ucode_amd_firmware_open(fwh, fwname);
+ case CPUVENDOR_INTEL:
+ return EOPNOTSUPP; /* not yet supported */
+ default:
+ return EOPNOTSUPP;
+ }
+}
+
+int
+cpu_ucode_apply(void *data)
+{
+ struct cpu_ucode *ucode = data;
+ struct cpu_ucode_softc *sc = &ucode_softc;
+ int error;
+
+ error = cpu_ucode_load(sc, ucode->fwname);
+ if (error)
+ return error;
+
+ switch (cpu_vendor) {
+ case CPUVENDOR_AMD:
+ error = cpu_ucode_amd_apply(sc);
+ break;
+ default:
+ return EOPNOTSUPP;
+ }
+
+ if (sc->sc_blob != NULL)
+ firmware_free(sc->sc_blob, 0);
+ sc->sc_blob = NULL;
+ sc->sc_blobsize = 0;
+ return error;
+}
Index: src/sys/arch/x86/x86/cpu_ucode_amd.c
diff -u /dev/null src/sys/arch/x86/x86/cpu_ucode_amd.c:1.1
--- /dev/null Fri Jan 13 16:05:16 2012
+++ src/sys/arch/x86/x86/cpu_ucode_amd.c Fri Jan 13 16:05:15 2012
@@ -0,0 +1,292 @@
+/* $NetBSD: cpu_ucode_amd.c,v 1.1 2012/01/13 16:05:15 cegger Exp $ */
+/*
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christoph Egger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: cpu_ucode_amd.c,v 1.1 2012/01/13 16:05:15 cegger Exp $");
+
+#include "opt_xen.h"
+#include "opt_cpu_ucode.h"
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/cpuio.h>
+#include <sys/cpu.h>
+#include <sys/kmem.h>
+#include <sys/xcall.h>
+
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+#include <x86/cpu_ucode.h>
+
+struct microcode_amd_header {
+ uint32_t ah_data_code;
+ uint32_t ah_patch_id;
+ uint8_t ah_patch_data_id[2];
+ uint8_t ah_patch_data_len;
+ uint8_t ah_init_flag;
+ uint32_t ah_patch_data_checksum;
+ uint32_t ah_nb_dev_id;
+ uint32_t ah_sb_dev_id;
+ uint16_t ah_processor_rev_id;
+ uint8_t ah_nb_rev_id;
+ uint8_t ah_sb_rev_id;
+ uint8_t ah_bios_api_rev;
+ uint8_t ah_reserved[3];
+ uint32_t ah_match_reg[8];
+} __packed;
+
+/* equivalence cpu table */
+struct microcode_amd_equiv_cpu_table {
+ uint32_t ect_installed_cpu;
+ uint32_t ect_fixed_errata_mask;
+ uint32_t ect_fixed_errata_compare;
+ uint16_t ect_equiv_cpu;
+ uint16_t ect_reserved;
+};
+
+#define UCODE_MAGIC 0x00414d44
+
+struct microcode_amd {
+ uint8_t *mpb; /* microcode patch block */
+ size_t mpb_size;
+ struct microcode_amd_equiv_cpu_table *ect;
+ size_t ect_size;
+};
+
+struct mpbhdr {
+#define UCODE_TYPE_EQUIV 0
+#define UCODE_TYPE_PATCH 1
+ uint32_t mpb_type;
+ uint32_t mpb_len;
+ uint32_t mpb_data[];
+};
+
+static uint32_t
+amd_cpufamily(void)
+{
+ uint32_t family;
+ struct cpu_info *ci = curcpu();
+
+ family = CPUID2FAMILY(ci->ci_signature);
+ if (family == 0xf)
+ family += CPUID2EXTFAMILY(ci->ci_signature);
+
+ return family;
+}
+
+int
+cpu_ucode_amd_get_version(struct cpu_ucode *ucode)
+{
+ if (amd_cpufamily() < 0x10) {
+ ucode->version = (uint64_t)-1;
+ return EOPNOTSUPP;
+ }
+
+ ucode->version = rdmsr(MSR_UCODE_AMD_PATCHLEVEL);
+ return 0;
+}
+
+int
+cpu_ucode_amd_firmware_open(firmware_handle_t *fwh, const char *fwname)
+{
+ const char *fw_path = "x86/amd";
+ char _fwname[32];
+ int error;
+
+ if (fwname != NULL && fwname[0] != '\0')
+ return firmware_open(fw_path, fwname, fwh);
+
+ snprintf(_fwname, sizeof(_fwname), "microcode_amd_fam%xh.bin",
+ amd_cpufamily());
+
+ error = firmware_open(fw_path, _fwname, fwh);
+ if (error == 0)
+ return 0;
+
+ return firmware_open(fw_path, "microcode_amd.bin", fwh);
+}
+
+#ifndef XEN
+struct mc_buf {
+ uint8_t *mc_buf;
+ uint32_t mc_equiv_cpuid;
+ struct mpbhdr *mc_mpbuf;
+ struct microcode_amd *mc_amd;
+ int mc_error;
+};
+
+static void
+cpu_apply_cb(void *arg0, void *arg1)
+{
+ int error = 0;
+ const struct cpu_ucode_softc *sc = arg0;
+ struct microcode_amd mc_amd;
+ struct mc_buf mc;
+ device_t dev;
+
+ memcpy(&mc, arg1, sizeof(mc));
+ mc_amd.mpb = mc.mc_amd->mpb;
+ mc_amd.mpb_size = mc.mc_amd->mpb_size;
+
+ dev = curcpu()->ci_dev;
+
+ do {
+ uint64_t patchlevel;
+ struct microcode_amd_header *hdr;
+
+ if (mc.mc_mpbuf->mpb_type != UCODE_TYPE_PATCH) {
+ aprint_debug_dev(dev, "ucode: patch type expected\n");
+ goto next;
+ }
+
+ hdr = (struct microcode_amd_header *)mc_amd.mpb;
+ if (hdr->ah_processor_rev_id != mc.mc_equiv_cpuid) {
+ aprint_debug_dev(dev, "ucode: patch does not"
+ "match this cpu "
+ "(patch is for cpu id %x, cpu id is %x)\n",
+ hdr->ah_processor_rev_id, mc.mc_equiv_cpuid);
+ goto next;
+ }
+
+ patchlevel = rdmsr(MSR_UCODE_AMD_PATCHLEVEL);
+ if (hdr->ah_patch_id <= patchlevel)
+ goto next;
+
+ /* found matching microcode update */
+ wrmsr(MSR_UCODE_AMD_PATCHLOADER, (u_long)hdr);
+
+ /* check current patch id and patch's id for match */
+ if (patchlevel == rdmsr(MSR_UCODE_AMD_PATCHLEVEL)) {
+ aprint_debug_dev(dev, "ucode: update from revision "
+ "0x%"PRIx64" to 0x%x failed\n",
+ patchlevel, hdr->ah_patch_id);
+ error = EIO;
+ goto out;
+ } else {
+ /* Success */
+ error = 0;
+ goto out;
+ }
+
+next:
+ mc.mc_buf += mc.mc_mpbuf->mpb_len +
+ sizeof(mc.mc_mpbuf->mpb_type) +
+ sizeof(mc.mc_mpbuf->mpb_len);
+ mc.mc_mpbuf = (struct mpbhdr *)mc.mc_buf;
+ mc_amd.mpb = (uint8_t *)mc.mc_mpbuf->mpb_data;
+ mc_amd.mpb_size = mc.mc_mpbuf->mpb_len;
+
+ } while ((uintptr_t)((mc.mc_buf) - (uint8_t *)sc->sc_blob) < sc->sc_blobsize);
+ aprint_error_dev(dev, "ucode: No newer patch available "
+ "for this cpu than is already installed.\n");
+ error = ENOENT;
+
+out:
+ if (error)
+ ((struct mc_buf *)(arg1))->mc_error = error;
+}
+
+int
+cpu_ucode_amd_apply(struct cpu_ucode_softc *sc)
+{
+ int i, error = 0;
+ uint32_t *magic;
+ uint32_t cpu_signature;
+ uint32_t equiv_cpuid = 0;
+ struct mc_buf mc;
+ int where;
+
+ cpu_signature = curcpu()->ci_signature;
+
+ KASSERT(sc->sc_blob != NULL);
+ magic = (uint32_t *)sc->sc_blob;
+ if (*magic != UCODE_MAGIC) {
+ aprint_error("ucode: wrong file magic\n");
+ return EINVAL;
+ }
+
+ mc.mc_buf = &sc->sc_blob[sizeof(*magic)];
+ mc.mc_mpbuf = (struct mpbhdr *)mc.mc_buf;
+
+ /* equivalence table is expected to come first */
+ if (mc.mc_mpbuf->mpb_type != UCODE_TYPE_EQUIV) {
+ aprint_error("ucode: missing equivalence table\n");
+ return EINVAL;
+ }
+
+ mc.mc_amd = kmem_zalloc(sizeof(*mc.mc_amd), KM_NOSLEEP);
+ if (mc.mc_amd == NULL)
+ return ENOMEM;
+
+ mc.mc_amd->ect = kmem_alloc(mc.mc_mpbuf->mpb_len, KM_NOSLEEP);
+ if (mc.mc_amd->ect == NULL) {
+ error = ENOMEM;
+ goto err0;
+ }
+
+ memcpy(mc.mc_amd->ect, mc.mc_mpbuf->mpb_data, mc.mc_mpbuf->mpb_len);
+ mc.mc_amd->ect_size = mc.mc_mpbuf->mpb_len;
+
+ /* check if there is a patch for this cpu present */
+ for (i = 0; mc.mc_amd->ect[i].ect_installed_cpu != 0; i++) {
+ if (cpu_signature == mc.mc_amd->ect[i].ect_installed_cpu) {
+ /* keep extended family and extended model */
+ equiv_cpuid = mc.mc_amd->ect[i].ect_equiv_cpu & 0xffff;
+ break;
+ }
+ }
+ if (equiv_cpuid == 0) {
+ aprint_error("ucode: No patch available for this cpu\n");
+ error = ENOENT;
+ goto err1;
+ }
+
+ mc.mc_equiv_cpuid = equiv_cpuid;
+ mc.mc_buf += mc.mc_mpbuf->mpb_len + sizeof(mc.mc_mpbuf->mpb_type) +
+ sizeof(mc.mc_mpbuf->mpb_len);
+ mc.mc_mpbuf = (struct mpbhdr *)mc.mc_buf;
+ mc.mc_amd->mpb = (uint8_t *)mc.mc_mpbuf->mpb_data;
+ mc.mc_amd->mpb_size = mc.mc_mpbuf->mpb_len;
+
+ /* Apply it on all cpus */
+ mc.mc_error = 0;
+ where = xc_broadcast(XC_HIGHPRI, cpu_apply_cb, sc, &mc);
+
+ /* Wait for completion */
+ xc_wait(where);
+ error = mc.mc_error;
+
+err1:
+ kmem_free(mc.mc_amd->ect, mc.mc_amd->ect_size);
+err0:
+ kmem_free(mc.mc_amd, sizeof(*mc.mc_amd));
+ return error;
+}
+#endif
Index: src/sys/arch/xen/xen/xen_ucode.c
diff -u /dev/null src/sys/arch/xen/xen/xen_ucode.c:1.1
--- /dev/null Fri Jan 13 16:05:16 2012
+++ src/sys/arch/xen/xen/xen_ucode.c Fri Jan 13 16:05:15 2012
@@ -0,0 +1,101 @@
+/* $NetBSD: xen_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $ */
+/*
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christoph Egger.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: xen_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $");
+
+#include "opt_cpu_ucode.h"
+
+#include <sys/param.h>
+#include <sys/cpuio.h>
+#include <sys/cpu.h>
+
+#include <dev/firmload.h>
+
+#include <machine/cpuvar.h>
+#include <machine/cputypes.h>
+
+#include <x86/cpu_ucode.h>
+
+static struct cpu_ucode_softc ucode_softc;
+
+int
+cpu_ucode_get_version(void *data)
+{
+ struct cpu_ucode *ucode = data;
+
+ switch (cpu_vendor) {
+ case CPUVENDOR_AMD:
+ return cpu_ucode_amd_get_version(ucode);
+ default:
+ ucode->version = (uint64_t)-1;
+ return EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+int
+cpu_ucode_md_open(firmware_handle_t *fwh, const char *fwname)
+{
+ switch (cpu_vendor) {
+ case CPUVENDOR_AMD:
+ return cpu_ucode_amd_firmware_open(fwh, fwname);
+ case CPUVENDOR_INTEL:
+ return EOPNOTSUPP; /* not yet supported */
+ default:
+ return EOPNOTSUPP;
+ }
+}
+
+int
+cpu_ucode_apply(void *data)
+{
+ struct cpu_ucode *ucode = data;
+ struct cpu_ucode_softc *sc = &ucode_softc;
+ struct xen_platform_op op;
+ int error;
+
+ error = cpu_ucode_load(sc, ucode->fwname);
+ if (error)
+ return error;
+
+ op.cmd = XENPF_microcode_update;
+ set_xen_guest_handle(op.u.microcode.data, sc->sc_blob);
+ op.u.microcode.length = sc->sc_blobsize;
+
+ error = -HYPERVISOR_platform_op(&op);
+
+ if (sc->sc_blob)
+ firmware_free(sc->sc_blob, 0);
+ sc->sc_blob = NULL;
+ sc->sc_blobsize = 0;
+ return error;
+}