Module Name:    src
Committed By:   drochner
Date:           Wed Aug 29 17:13:23 UTC 2012

Modified Files:
        src/distrib/sets/lists/comp: md.amd64 md.i386
        src/sys/arch/x86/conf: files.x86
        src/sys/arch/x86/include: Makefile cpu_ucode.h
        src/sys/arch/x86/x86: cpu_ucode.c cpu_ucode_amd.c
        src/sys/arch/xen/conf: files.xen
        src/sys/arch/xen/xen: xen_ucode.c
        src/sys/kern: kern_cpu.c
        src/sys/sys: cpu.h cpuio.h
        src/usr.sbin/cpuctl: cpuctl.c cpuctl.h
        src/usr.sbin/cpuctl/arch: i386.c noarch.c
Added Files:
        src/sys/arch/x86/x86: cpu_ucode_intel.c
        src/sys/compat/sys: cpuio.h

Log Message:
Extend the CPU microcode update framework to support Intel x86 CPUs.
Contrary to the AMD implementation, it doesn't use xcalls to distribute
the update to all CPUs but relies on cpuctl(8) to bind itself to the
right CPU -- to keep it simple and avoid possible problems with
hyperthreading.
Also, it doesn't parse the vendor supplied file to pick the right
part for the present CPU model but relies on userland to prepare
files with specific filenames. I'll commit a pkg for this in a minute
(pkgsrc/sysutils/intel-microcode).
The ioctl interface changed; compatibility is provided (should be
limited to COMPAT_NETBSD6 as soon as this is available).


To generate a diff of this commit:
cvs rdiff -u -r1.175 -r1.176 src/distrib/sets/lists/comp/md.amd64
cvs rdiff -u -r1.126 -r1.127 src/distrib/sets/lists/comp/md.i386
cvs rdiff -u -r1.78 -r1.79 src/sys/arch/x86/conf/files.x86
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/x86/include/Makefile
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/x86/include/cpu_ucode.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/x86/x86/cpu_ucode.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/x86/x86/cpu_ucode_amd.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/x86/cpu_ucode_intel.c
cvs rdiff -u -r1.127 -r1.128 src/sys/arch/xen/conf/files.xen
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/xen/xen/xen_ucode.c
cvs rdiff -u -r0 -r1.4 src/sys/compat/sys/cpuio.h
cvs rdiff -u -r1.56 -r1.57 src/sys/kern/kern_cpu.c
cvs rdiff -u -r1.35 -r1.36 src/sys/sys/cpu.h
cvs rdiff -u -r1.7 -r1.8 src/sys/sys/cpuio.h
cvs rdiff -u -r1.20 -r1.21 src/usr.sbin/cpuctl/cpuctl.c
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/cpuctl/cpuctl.h
cvs rdiff -u -r1.31 -r1.32 src/usr.sbin/cpuctl/arch/i386.c
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/cpuctl/arch/noarch.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/comp/md.amd64
diff -u src/distrib/sets/lists/comp/md.amd64:1.175 src/distrib/sets/lists/comp/md.amd64:1.176
--- src/distrib/sets/lists/comp/md.amd64:1.175	Fri Aug 10 16:22:33 2012
+++ src/distrib/sets/lists/comp/md.amd64	Wed Aug 29 17:13:21 2012
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.175 2012/08/10 16:22:33 joerg Exp $
+# $NetBSD: md.amd64,v 1.176 2012/08/29 17:13:21 drochner Exp $
 ./usr/include/amd64				comp-c-include
 ./usr/include/amd64/ansi.h			comp-c-include
 ./usr/include/amd64/aout_machdep.h		comp-c-include
@@ -283,6 +283,7 @@
 ./usr/include/x86/bus.h				comp-obsolete		obsolete
 ./usr/include/x86/cacheinfo.h			comp-c-include
 ./usr/include/x86/cpu.h				comp-c-include
+./usr/include/x86/cpu_ucode.h			comp-c-include
 ./usr/include/x86/cputypes.h			comp-c-include
 ./usr/include/x86/cpuvar.h			comp-c-include
 ./usr/include/x86/float.h			comp-c-include

Index: src/distrib/sets/lists/comp/md.i386
diff -u src/distrib/sets/lists/comp/md.i386:1.126 src/distrib/sets/lists/comp/md.i386:1.127
--- src/distrib/sets/lists/comp/md.i386:1.126	Wed Aug  8 18:37:51 2012
+++ src/distrib/sets/lists/comp/md.i386	Wed Aug 29 17:13:21 2012
@@ -1,4 +1,4 @@
-# $NetBSD: md.i386,v 1.126 2012/08/08 18:37:51 drochner Exp $
+# $NetBSD: md.i386,v 1.127 2012/08/29 17:13:21 drochner Exp $
 ./usr/include/clang-3.0/avxintrin.h		comp-obsolete		obsolete
 ./usr/include/clang-3.0/avx2intrin.h		comp-obsolete		obsolete
 ./usr/include/clang-3.0/bmi2intrin.h		comp-obsolete		obsolete
@@ -165,6 +165,7 @@
 ./usr/include/x86/bus.h				comp-obsolete		obsolete
 ./usr/include/x86/cacheinfo.h			comp-c-include
 ./usr/include/x86/cpu.h				comp-c-include
+./usr/include/x86/cpu_ucode.h			comp-c-include
 ./usr/include/x86/cputypes.h			comp-c-include
 ./usr/include/x86/cpuvar.h			comp-c-include
 ./usr/include/x86/float.h			comp-c-include

Index: src/sys/arch/x86/conf/files.x86
diff -u src/sys/arch/x86/conf/files.x86:1.78 src/sys/arch/x86/conf/files.x86:1.79
--- src/sys/arch/x86/conf/files.x86:1.78	Mon May  7 17:45:29 2012
+++ src/sys/arch/x86/conf/files.x86	Wed Aug 29 17:13:21 2012
@@ -1,4 +1,4 @@
-#	$NetBSD: files.x86,v 1.78 2012/05/07 17:45:29 jym Exp $
+#	$NetBSD: files.x86,v 1.79 2012/08/29 17:13:21 drochner Exp $
 
 # options for MP configuration through the MP spec
 defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
@@ -96,6 +96,7 @@ file	arch/x86/x86/x86_machdep.c
 
 file	arch/x86/x86/cpu_ucode.c	cpu_ucode needs-flag
 file	arch/x86/x86/cpu_ucode_amd.c	cpu_ucode needs-flag
+file	arch/x86/x86/cpu_ucode_intel.c	cpu_ucode needs-flag
 
 define	lapic
 file	arch/x86/x86/lapic.c		lapic needs-flag

Index: src/sys/arch/x86/include/Makefile
diff -u src/sys/arch/x86/include/Makefile:1.16 src/sys/arch/x86/include/Makefile:1.17
--- src/sys/arch/x86/include/Makefile:1.16	Sun Jul 17 23:38:32 2011
+++ src/sys/arch/x86/include/Makefile	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-# 	$NetBSD: Makefile,v 1.16 2011/07/17 23:38:32 dyoung Exp $
+# 	$NetBSD: Makefile,v 1.17 2012/08/29 17:13:22 drochner Exp $
 
 INCSDIR=/usr/include/x86
 
@@ -6,6 +6,7 @@ INCS=	aout_machdep.h \
 	bootinfo.h \
 	cacheinfo.h \
 	cpu.h \
+	cpu_ucode.h \
 	cputypes.h \
 	cpuvar.h \
 	float.h \

Index: src/sys/arch/x86/include/cpu_ucode.h
diff -u src/sys/arch/x86/include/cpu_ucode.h:1.1 src/sys/arch/x86/include/cpu_ucode.h:1.2
--- src/sys/arch/x86/include/cpu_ucode.h:1.1	Fri Jan 13 16:05:14 2012
+++ src/sys/arch/x86/include/cpu_ucode.h	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_ucode.h,v 1.1 2012/01/13 16:05:14 cegger Exp $ */
+/* $NetBSD: cpu_ucode.h,v 1.2 2012/08/29 17:13:22 drochner Exp $ */
 /*
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -31,12 +31,57 @@
 #ifndef _X86_CPU_UCODE_H_
 #define _X86_CPU_UCODE_H_
 
+#define CPU_UCODE_LOADER_AMD 0
+struct cpu_ucode_version_amd {
+	uint64_t version;
+};
+
+#define CPU_UCODE_LOADER_INTEL1 1
+struct cpu_ucode_version_intel1 {
+	uint32_t ucodeversion;
+	int platformid;
+};
+
+#ifdef _KERNEL
 #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_get_version(struct cpu_ucode_version *);
+/* XXX COMPAT */
+int compat6_cpu_ucode_amd_get_version(struct compat6_cpu_ucode *);
 int cpu_ucode_amd_firmware_open(firmware_handle_t *, const char *);
-int cpu_ucode_amd_apply(struct cpu_ucode_softc *);
+int cpu_ucode_amd_apply(struct cpu_ucode_softc *, int);
+
+int cpu_ucode_intel_get_version(struct cpu_ucode_version *);
+int cpu_ucode_intel_firmware_open(firmware_handle_t *, const char *);
+int cpu_ucode_intel_apply(struct cpu_ucode_softc *, int);
+#endif /* _KERNEL */
+
+struct intel1_ucode_header {
+	uint32_t	uh_header_ver;
+	uint32_t	uh_rev;
+	uint32_t	uh_date;
+	uint32_t	uh_signature;
+	uint32_t	uh_checksum;
+	uint32_t	uh_loader_rev;
+	uint32_t	uh_proc_flags;
+	uint32_t	uh_data_size;
+	uint32_t	uh_total_size;
+	uint32_t	uh_reserved[3];
+};
+
+struct intel1_ucode_proc_signature {
+	uint32_t	ups_signature;
+	uint32_t	ups_proc_flags;
+	uint32_t	ups_checksum;
+};
+
+struct intel1_ucode_ext_table {
+	uint32_t	uet_count;
+	uint32_t	uet_checksum;
+	uint32_t	uet_reserved[3];
+	struct intel1_ucode_proc_signature uet_proc_sig[1];
+};
 
 #endif

Index: src/sys/arch/x86/x86/cpu_ucode.c
diff -u src/sys/arch/x86/x86/cpu_ucode.c:1.1 src/sys/arch/x86/x86/cpu_ucode.c:1.2
--- src/sys/arch/x86/x86/cpu_ucode.c:1.1	Fri Jan 13 16:05:15 2012
+++ src/sys/arch/x86/x86/cpu_ucode.c	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $ */
+/* $NetBSD: cpu_ucode.c,v 1.2 2012/08/29 17:13:22 drochner Exp $ */
 /*
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu_ucode.c,v 1.2 2012/08/29 17:13:22 drochner Exp $");
 
 #include "opt_cpu_ucode.h"
 
@@ -47,48 +47,67 @@ __KERNEL_RCSID(0, "$NetBSD: cpu_ucode.c,
 static struct cpu_ucode_softc ucode_softc;
 
 int
-cpu_ucode_get_version(void *data)
+cpu_ucode_get_version(struct cpu_ucode_version *data)
 {
-	struct cpu_ucode *ucode = data;
 
 	switch (cpu_vendor) {
 	case CPUVENDOR_AMD:
-		return cpu_ucode_amd_get_version(ucode);
+		return cpu_ucode_amd_get_version(data);
+	case CPUVENDOR_INTEL:
+		return cpu_ucode_intel_get_version(data);
 	default:
-		ucode->version = (uint64_t)-1;
 		return EOPNOTSUPP;
 	}
 
 	return 0;
 }
 
+/* XXX COMPAT */
 int
-cpu_ucode_md_open(firmware_handle_t *fwh, const char *fwname)
+compat6_cpu_ucode_get_version(struct compat6_cpu_ucode *data)
+{
+
+	switch (cpu_vendor) {
+	case CPUVENDOR_AMD:
+		return compat6_cpu_ucode_amd_get_version(data);
+	default:
+		return EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+int
+cpu_ucode_md_open(firmware_handle_t *fwh, int loader_version, 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 */
+		return cpu_ucode_intel_firmware_open(fwh, fwname);
 	default:
 		return EOPNOTSUPP;
 	}
 }
 
 int
-cpu_ucode_apply(void *data)
+cpu_ucode_apply(const struct cpu_ucode *data)
 {
-	struct cpu_ucode *ucode = data;
 	struct cpu_ucode_softc *sc = &ucode_softc;
 	int error;
 
-	error = cpu_ucode_load(sc, ucode->fwname);
+	sc->loader_version = data->loader_version;
+
+	error = cpu_ucode_load(sc, data->fwname);
 	if (error)
 		return error;
 
 	switch (cpu_vendor) {
 	case CPUVENDOR_AMD:
-		error = cpu_ucode_amd_apply(sc);
+		error = cpu_ucode_amd_apply(sc, data->cpu_nr);
+		break;
+	case CPUVENDOR_INTEL:
+		error = cpu_ucode_intel_apply(sc, data->cpu_nr);
 		break;
 	default:
 		return EOPNOTSUPP;
@@ -100,3 +119,27 @@ cpu_ucode_apply(void *data)
 	sc->sc_blobsize = 0;
 	return error;
 }
+
+/* XXX COMPAT */
+int
+compat6_cpu_ucode_apply(const struct compat6_cpu_ucode *data)
+{
+	struct cpu_ucode_softc *sc = &ucode_softc;
+	int error;
+
+	if (cpu_vendor != CPUVENDOR_AMD)
+		return EOPNOTSUPP;
+
+	sc->loader_version = CPU_UCODE_LOADER_AMD;
+	error = cpu_ucode_load(sc, data->fwname);
+	if (error)
+		return error;
+
+	error = cpu_ucode_amd_apply(sc, CPU_UCODE_ALL_CPUS);
+
+	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 src/sys/arch/x86/x86/cpu_ucode_amd.c:1.3 src/sys/arch/x86/x86/cpu_ucode_amd.c:1.4
--- src/sys/arch/x86/x86/cpu_ucode_amd.c:1.3	Thu May 10 12:35:53 2012
+++ src/sys/arch/x86/x86/cpu_ucode_amd.c	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_ucode_amd.c,v 1.3 2012/05/10 12:35:53 cegger Exp $ */
+/* $NetBSD: cpu_ucode_amd.c,v 1.4 2012/08/29 17:13:22 drochner Exp $ */
 /*
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu_ucode_amd.c,v 1.3 2012/05/10 12:35:53 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu_ucode_amd.c,v 1.4 2012/08/29 17:13:22 drochner Exp $");
 
 #include "opt_xen.h"
 #include "opt_cpu_ucode.h"
@@ -102,14 +102,29 @@ amd_cpufamily(void)
 }
 
 int
-cpu_ucode_amd_get_version(struct cpu_ucode *ucode)
+cpu_ucode_amd_get_version(struct cpu_ucode_version *ucode)
 {
-	if (amd_cpufamily() < 0x10) {
-		ucode->version = (uint64_t)-1;
+	struct cpu_ucode_version_amd data;
+
+	if (ucode->loader_version != CPU_UCODE_LOADER_AMD || amd_cpufamily() < 0x10)
+		return EOPNOTSUPP;
+	if (!ucode->data)
+		return 0;
+
+	data.version = rdmsr(MSR_UCODE_AMD_PATCHLEVEL);
+	return copyout(&data, ucode->data, sizeof(data));
+}
+
+int
+compat6_cpu_ucode_amd_get_version(struct compat6_cpu_ucode *ucode)
+{
+	uint64_t uclevel;
+
+	if (amd_cpufamily() < 0x10)
 		return EOPNOTSUPP;
-	}
 
-	ucode->version = rdmsr(MSR_UCODE_AMD_PATCHLEVEL);
+	uclevel = rdmsr(MSR_UCODE_AMD_PATCHLEVEL);
+	ucode->version = uclevel;
 	return 0;
 }
 
@@ -227,7 +242,7 @@ out:
 }
 
 int
-cpu_ucode_amd_apply(struct cpu_ucode_softc *sc)
+cpu_ucode_amd_apply(struct cpu_ucode_softc *sc, int cpuno)
 {
 	int i, error = 0;
 	uint32_t *magic;
@@ -236,6 +251,10 @@ cpu_ucode_amd_apply(struct cpu_ucode_sof
 	struct mc_buf mc;
 	int where;
 
+	if (sc->loader_version != CPU_UCODE_LOADER_AMD
+	    || cpuno != CPU_UCODE_ALL_CPUS)
+		return EINVAL;
+
 	cpu_signature = curcpu()->ci_signature;
 
 	KASSERT(sc->sc_blob != NULL);

Index: src/sys/arch/xen/conf/files.xen
diff -u src/sys/arch/xen/conf/files.xen:1.127 src/sys/arch/xen/conf/files.xen:1.128
--- src/sys/arch/xen/conf/files.xen:1.127	Wed Jun 27 00:37:09 2012
+++ src/sys/arch/xen/conf/files.xen	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-#	$NetBSD: files.xen,v 1.127 2012/06/27 00:37:09 jym Exp $
+#	$NetBSD: files.xen,v 1.128 2012/08/29 17:13:22 drochner 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 
 
@@ -94,6 +94,7 @@ file	arch/xen/x86/xenfunc.c
 
 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/x86/x86/cpu_ucode_intel.c	dom0ops | cpu_ucode needs-flag
 
 file	arch/xen/xen/xen_machdep.c
 file	arch/xen/xen/xen_debug.c

Index: src/sys/arch/xen/xen/xen_ucode.c
diff -u src/sys/arch/xen/xen/xen_ucode.c:1.1 src/sys/arch/xen/xen/xen_ucode.c:1.2
--- src/sys/arch/xen/xen/xen_ucode.c:1.1	Fri Jan 13 16:05:15 2012
+++ src/sys/arch/xen/xen/xen_ucode.c	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $ */
+/* $NetBSD: xen_ucode.c,v 1.2 2012/08/29 17:13:22 drochner Exp $ */
 /*
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xen_ucode.c,v 1.1 2012/01/13 16:05:15 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_ucode.c,v 1.2 2012/08/29 17:13:22 drochner Exp $");
 
 #include "opt_cpu_ucode.h"
 
@@ -47,15 +47,30 @@ __KERNEL_RCSID(0, "$NetBSD: xen_ucode.c,
 static struct cpu_ucode_softc ucode_softc;
 
 int
-cpu_ucode_get_version(void *data)
+cpu_ucode_get_version(struct cpu_ucode_version *data)
 {
-	struct cpu_ucode *ucode = data;
 
 	switch (cpu_vendor) {
 	case CPUVENDOR_AMD:
-		return cpu_ucode_amd_get_version(ucode);
+		return cpu_ucode_amd_get_version(data);
+	case CPUVENDOR_INTEL:
+		return cpu_ucode_intel_get_version(data);
+	default:
+		return EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+/* XXX COMPAT */
+int
+compat6_cpu_ucode_get_version(struct compat6_cpu_ucode *data)
+{
+
+	switch (cpu_vendor) {
+	case CPUVENDOR_AMD:
+		return compat6_cpu_ucode_amd_get_version(data);
 	default:
-		ucode->version = (uint64_t)-1;
 		return EOPNOTSUPP;
 	}
 
@@ -63,27 +78,31 @@ cpu_ucode_get_version(void *data)
 }
 
 int
-cpu_ucode_md_open(firmware_handle_t *fwh, const char *fwname)
+cpu_ucode_md_open(firmware_handle_t *fwh, int loader_version, 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 */
+		return cpu_ucode_intel_firmware_open(fwh, fwname);
 	default:
 		return EOPNOTSUPP;
 	}
 }
 
 int
-cpu_ucode_apply(void *data)
+cpu_ucode_apply(const struct cpu_ucode *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);
+	/* Xen updates all??? */
+	if (data->cpu_nr != CPU_UCODE_ALL_CPUS)
+		return EOPNOTSUPP;
+
+	sc->loader_version = data->loader_version;
+	error = cpu_ucode_load(sc, data->fwname);
 	if (error)
 		return error;
 
@@ -99,3 +118,28 @@ cpu_ucode_apply(void *data)
 	sc->sc_blobsize = 0;
 	return error;
 }
+
+int
+compat6_cpu_ucode_apply(const struct compat6_cpu_ucode *data)
+{
+	struct cpu_ucode_softc *sc = &ucode_softc;
+	struct xen_platform_op op;
+	int error;
+
+	sc->loader_version = CPU_UCODE_LOADER_AMD;
+	error = cpu_ucode_load(sc, data->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 != NULL)
+		firmware_free(sc->sc_blob, 0);
+	sc->sc_blob = NULL;
+	sc->sc_blobsize = 0;
+	return error;
+}

Index: src/sys/kern/kern_cpu.c
diff -u src/sys/kern/kern_cpu.c:1.56 src/sys/kern/kern_cpu.c:1.57
--- src/sys/kern/kern_cpu.c:1.56	Wed Jun 13 23:00:05 2012
+++ src/sys/kern/kern_cpu.c	Wed Aug 29 17:13:21 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_cpu.c,v 1.56 2012/06/13 23:00:05 joerg Exp $	*/
+/*	$NetBSD: kern_cpu.c,v 1.57 2012/08/29 17:13:21 drochner Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009, 2010, 2012 The NetBSD Foundation, Inc.
@@ -56,9 +56,10 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.56 2012/06/13 23:00:05 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.57 2012/08/29 17:13:21 drochner Exp $");
 
 #include "opt_cpu_ucode.h"
+#include "opt_compat_netbsd.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -265,7 +266,12 @@ cpuctl_ioctl(dev_t dev, u_long cmd, void
 
 #ifdef CPU_UCODE
 	case IOC_CPU_UCODE_GET_VERSION:
-		error = cpu_ucode_get_version(data);
+		error = cpu_ucode_get_version((struct cpu_ucode_version *)data);
+		break;
+
+	/* XXX ifdef COMPAT */
+	case OIOC_CPU_UCODE_GET_VERSION:
+		error = compat6_cpu_ucode_get_version((struct compat6_cpu_ucode *)data);
 		break;
 
 	case IOC_CPU_UCODE_APPLY:
@@ -274,7 +280,17 @@ cpuctl_ioctl(dev_t dev, u_long cmd, void
 		    NULL, NULL, NULL, NULL);
 		if (error != 0)
 			break;
-		error = cpu_ucode_apply(data);
+		error = cpu_ucode_apply((const struct cpu_ucode *)data);
+		break;
+
+	/* XXX ifdef COMPAT */
+	case OIOC_CPU_UCODE_APPLY:
+		error = kauth_authorize_machdep(l->l_cred,
+		    KAUTH_MACHDEP_CPU_UCODE_APPLY,
+		    NULL, NULL, NULL, NULL);
+		if (error != 0)
+			break;
+		error = compat6_cpu_ucode_apply((const struct compat6_cpu_ucode *)data);
 		break;
 #endif
 
@@ -554,7 +570,7 @@ cpu_ucode_load(struct cpu_ucode_softc *s
 		sc->sc_blobsize = 0;
 	}
 
-	error = cpu_ucode_md_open(&fwh, fwname);
+	error = cpu_ucode_md_open(&fwh, sc->loader_version, fwname);
 	if (error != 0) {
 		aprint_error("ucode: firmware_open failed: %i\n", error);
 		goto err0;

Index: src/sys/sys/cpu.h
diff -u src/sys/sys/cpu.h:1.35 src/sys/sys/cpu.h:1.36
--- src/sys/sys/cpu.h:1.35	Sun Jan 29 22:55:40 2012
+++ src/sys/sys/cpu.h	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.35 2012/01/29 22:55:40 rmind Exp $	*/
+/*	$NetBSD: cpu.h,v 1.36 2012/08/29 17:13:22 drochner Exp $	*/
 
 /*-
  * Copyright (c) 2007 YAMAMOTO Takashi,
@@ -43,7 +43,11 @@ void cpu_idle(void);
 #endif
 
 #ifdef CPU_UCODE
+#include <sys/cpuio.h>
 #include <dev/firmload.h>
+
+/* XXX ifdef COMPAT */
+#include <compat/sys/cpuio.h>
 #endif
 
 /*
@@ -110,14 +114,19 @@ cpu_name(struct cpu_info *ci)
 
 #ifdef CPU_UCODE
 struct cpu_ucode_softc {
+	int loader_version;
 	char *sc_blob;
 	off_t sc_blobsize;
 };
 
-int cpu_ucode_get_version(void *);
-int cpu_ucode_apply(void *);
+int cpu_ucode_get_version(struct cpu_ucode_version *);
+/* XXX ifdef COMPAT */
+int compat6_cpu_ucode_get_version(struct compat6_cpu_ucode *);
+int cpu_ucode_apply(const struct cpu_ucode *);
+/* XXX ifdef COMPAT */
+int compat6_cpu_ucode_apply(const struct compat6_cpu_ucode *);
 int cpu_ucode_load(struct cpu_ucode_softc *, const char *);
-int cpu_ucode_md_open(firmware_handle_t *, const char *);
+int cpu_ucode_md_open(firmware_handle_t *, int, const char *);
 #endif
 
 #endif

Index: src/sys/sys/cpuio.h
diff -u src/sys/sys/cpuio.h:1.7 src/sys/sys/cpuio.h:1.8
--- src/sys/sys/cpuio.h:1.7	Mon Jan 16 10:36:16 2012
+++ src/sys/sys/cpuio.h	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuio.h,v 1.7 2012/01/16 10:36:16 cegger Exp $	*/
+/*	$NetBSD: cpuio.h,v 1.8 2012/08/29 17:13:22 drochner Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2009, 2012 The NetBSD Foundation, Inc.
@@ -62,13 +62,22 @@ typedef struct cpustate {
 #define	IOC_CPU_GETSTATE	_IOWR('c', 1, cpustate_t)
 #define	IOC_CPU_GETCOUNT	_IOR('c', 2, int)
 #define	IOC_CPU_MAPID		_IOWR('c', 3, int)
+/* 4 and 5 reserved for compat nb6 x86 amd ucode loader */
+
+struct cpu_ucode_version {
+	int loader_version;	/* IN: md version number */
+	void *data;		/* OUT: CPU ID data */
+};
 
 struct cpu_ucode {
-	uint64_t version;
+	int loader_version;	/* md version number */
+	int cpu_nr;		/* CPU index or special value below */
+#define CPU_UCODE_ALL_CPUS (-1)
+#define CPU_UCODE_CURRENT_CPU (-2)
 	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)
+#define IOC_CPU_UCODE_GET_VERSION	_IOWR('c', 6, struct cpu_ucode_version)
+#define IOC_CPU_UCODE_APPLY		_IOW('c', 7, struct cpu_ucode)
 
 #endif /* !_SYS_CPUIO_H_ */

Index: src/usr.sbin/cpuctl/cpuctl.c
diff -u src/usr.sbin/cpuctl/cpuctl.c:1.20 src/usr.sbin/cpuctl/cpuctl.c:1.21
--- src/usr.sbin/cpuctl/cpuctl.c:1.20	Fri Jan 13 16:05:16 2012
+++ src/usr.sbin/cpuctl/cpuctl.c	Wed Aug 29 17:13:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuctl.c,v 1.20 2012/01/13 16:05:16 cegger Exp $	*/
+/*	$NetBSD: cpuctl.c,v 1.21 2012/08/29 17:13:22 drochner Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009, 2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #ifndef lint
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: cpuctl.c,v 1.20 2012/01/13 16:05:16 cegger Exp $");
+__RCSID("$NetBSD: cpuctl.c,v 1.21 2012/08/29 17:13:22 drochner Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -192,12 +192,38 @@ cpu_ucode(char **argv)
 {
 	int error;
 	struct cpu_ucode uc;
+	unsigned long id = 0; /* gcc */
+	char *ep;
+	cpuset_t *cpuset;
 
+	uc.cpu_nr = -1;
+	if (argv[0] != NULL) {
+		id = strtoul(argv[0], &ep, 0);
+		if (id != ULONG_MAX && *ep == '\0') {
+			uc.cpu_nr = id;
+			argv++;
+		}
+	}
 	if (argv[0] != NULL)
 		strlcpy(uc.fwname, argv[0], sizeof(uc.fwname));
 	else
 		memset(uc.fwname, '\0', sizeof(uc.fwname));
 
+	error = ucodeupdate_check(fd, &uc);
+	if (error)
+		errx(EXIT_FAILURE, "unsupported");
+
+	if (uc.cpu_nr == CPU_UCODE_CURRENT_CPU) {
+		cpuset = cpuset_create();
+		if (cpuset == NULL)
+			err(EXIT_FAILURE, "cpuset_create");
+		cpuset_zero(cpuset);
+		cpuset_set(id, cpuset);
+		if (_sched_setaffinity(0, 0, cpuset_size(cpuset), cpuset) < 0) {
+			err(EXIT_FAILURE, "_sched_setaffinity");
+		}
+		cpuset_destroy(cpuset);
+	}
 	error = ioctl(fd, IOC_CPU_UCODE_APPLY, &uc);
 	if (error < 0) {
 		if (uc.fwname[0])
@@ -214,8 +240,6 @@ 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);
@@ -238,17 +262,7 @@ 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);
+	identifycpu(fd, name);
 }
 
 static u_int

Index: src/usr.sbin/cpuctl/cpuctl.h
diff -u src/usr.sbin/cpuctl/cpuctl.h:1.3 src/usr.sbin/cpuctl/cpuctl.h:1.4
--- src/usr.sbin/cpuctl/cpuctl.h:1.3	Thu Mar 15 02:02:23 2012
+++ src/usr.sbin/cpuctl/cpuctl.h	Wed Aug 29 17:13:23 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuctl.h,v 1.3 2012/03/15 02:02:23 joerg Exp $	*/
+/*	$NetBSD: cpuctl.h,v 1.4 2012/08/29 17:13:23 drochner Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -33,4 +33,5 @@ int	aprint_normal_dev(const char *, cons
 int	aprint_verbose_dev(const char *, const char *, ...) __printflike(2, 3);
 int	aprint_error_dev(const char *, const char *, ...) __printflike(2, 3);
 
-void	identifycpu(const char *);
+void	identifycpu(int, const char *);
+int	ucodeupdate_check(int, struct cpu_ucode *);

Index: src/usr.sbin/cpuctl/arch/i386.c
diff -u src/usr.sbin/cpuctl/arch/i386.c:1.31 src/usr.sbin/cpuctl/arch/i386.c:1.32
--- src/usr.sbin/cpuctl/arch/i386.c:1.31	Tue Apr 17 13:00:09 2012
+++ src/usr.sbin/cpuctl/arch/i386.c	Wed Aug 29 17:13:23 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386.c,v 1.31 2012/04/17 13:00:09 cegger Exp $	*/
+/*	$NetBSD: i386.c,v 1.32 2012/08/29 17:13:23 drochner Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -57,13 +57,14 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: i386.c,v 1.31 2012/04/17 13:00:09 cegger Exp $");
+__RCSID("$NetBSD: i386.c,v 1.32 2012/08/29 17:13:23 drochner Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/bitops.h>
 #include <sys/sysctl.h>
+#include <sys/cpuio.h>
 
 #include <string.h>
 #include <stdio.h>
@@ -79,6 +80,7 @@ __RCSID("$NetBSD: i386.c,v 1.31 2012/04/
 #include <x86/cpuvar.h>
 #include <x86/cputypes.h>
 #include <x86/cacheinfo.h>
+#include <x86/cpu_ucode.h>
 
 #include "../cpuctl.h"
 
@@ -1233,7 +1235,7 @@ transmeta_cpu_info(struct cpu_info *ci)
 }
 
 void
-identifycpu(const char *cpuname)
+identifycpu(int fd, const char *cpuname)
 {
 	const char *name = "", *modifier, *vendorname, *brand = "";
 	int class = CPUCLASS_386, i, xmax;
@@ -1248,6 +1250,11 @@ identifycpu(const char *cpuname)
 	size_t sz;
 	char buf[512];
 	char *bp;
+	struct cpu_ucode_version ucode;
+	union {
+		struct cpu_ucode_version_amd amd;
+		struct cpu_ucode_version_intel1 intel1;
+	} ucvers;
 
 	ci = &cistore;
 	memset(ci, 0, sizeof(*ci));
@@ -1519,6 +1526,21 @@ identifycpu(const char *cpuname)
 	    CPUID2FAMILY(ci->ci_signature), CPUID2MODEL(ci->ci_signature),
 	    CPUID2EXTFAMILY(ci->ci_signature), CPUID2EXTMODEL(ci->ci_signature),
 	    CPUID2STEPPING(ci->ci_signature));
+
+	if (cpu_vendor == CPUVENDOR_AMD)
+		ucode.loader_version = CPU_UCODE_LOADER_AMD;
+	else if (cpu_vendor == CPUVENDOR_INTEL)
+		ucode.loader_version = CPU_UCODE_LOADER_INTEL1;
+	else
+		return;
+	ucode.data = &ucvers;
+	if (ioctl(fd, IOC_CPU_UCODE_GET_VERSION, &ucode) < 0)
+		return;
+	if (cpu_vendor == CPUVENDOR_AMD)
+		printf("%s: UCode version: 0x%"PRIx64"\n", cpuname, ucvers.amd.version);
+	else if (cpu_vendor == CPUVENDOR_INTEL)
+		printf("%s: microcode version 0x%x, platform ID %d\n", cpuname,
+		       ucvers.intel1.ucodeversion, ucvers.intel1.platformid);
 }
 
 static const char *
@@ -1996,3 +2018,49 @@ powernow_probe(struct cpu_info *ci)
 	aprint_normal_dev(ci->ci_dev, "AMD Power Management features: %s\n",
 	    buf);
 }
+
+int
+ucodeupdate_check(int fd, struct cpu_ucode *uc)
+{
+	struct cpu_info ci;
+	int loader_version, res;
+	struct cpu_ucode_version versreq;
+	extern int cpu_info_level;
+
+	x86_identify();
+	ci.ci_cpuid_level = cpu_info_level;
+	cpu_probe_base_features(&ci);
+	if (!strcmp((char *)ci.ci_vendor, "AuthenticAMD"))
+		loader_version = CPU_UCODE_LOADER_AMD;
+	else if (!strcmp((char *)ci.ci_vendor, "GenuineIntel"))
+		loader_version = CPU_UCODE_LOADER_INTEL1;
+	else
+		return -1;
+
+	/* check whether the kernel understands this loader version */
+	versreq.loader_version = loader_version;
+	versreq.data = 0;
+	res = ioctl(fd, IOC_CPU_UCODE_GET_VERSION, &versreq);
+	if (res)
+		return -1;
+
+	switch (loader_version) {
+	case CPU_UCODE_LOADER_AMD:
+		if (uc->cpu_nr != -1) {
+			/* printf? */
+			return -1;
+		}
+		uc->cpu_nr = CPU_UCODE_ALL_CPUS;
+		break;
+	case CPU_UCODE_LOADER_INTEL1:
+		if (uc->cpu_nr == -1)
+			uc->cpu_nr = CPU_UCODE_ALL_CPUS; /* for Xen */
+		else
+			uc->cpu_nr = CPU_UCODE_CURRENT_CPU;
+		break;
+	default: /* can't happen */
+		return -1;
+	}
+	uc->loader_version = loader_version;
+	return 0;
+}

Index: src/usr.sbin/cpuctl/arch/noarch.c
diff -u src/usr.sbin/cpuctl/arch/noarch.c:1.2 src/usr.sbin/cpuctl/arch/noarch.c:1.3
--- src/usr.sbin/cpuctl/arch/noarch.c:1.2	Tue May  6 09:10:25 2008
+++ src/usr.sbin/cpuctl/arch/noarch.c	Wed Aug 29 17:13:23 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: noarch.c,v 1.2 2008/05/06 09:10:25 skrll Exp $	*/
+/*	$NetBSD: noarch.c,v 1.3 2012/08/29 17:13:23 drochner Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
 #include <sys/types.h>
 
 #ifndef lint
-__RCSID("$NetBSD: noarch.c,v 1.2 2008/05/06 09:10:25 skrll Exp $");
+__RCSID("$NetBSD: noarch.c,v 1.3 2012/08/29 17:13:23 drochner Exp $");
 #endif /* not lint */
 
 #include <stdio.h>
@@ -38,8 +38,15 @@ __RCSID("$NetBSD: noarch.c,v 1.2 2008/05
 #include "../cpuctl.h"
 
 void
-identifycpu(const char *cpuname)
+identifycpu(int fd, const char *cpuname)
 {
 
 	printf("CPU identification not implemented for this architecture.\n");
 }
+
+int
+ucodeupdate_check(int, struct cpu_ucode *uc)
+{
+
+	return 0;
+}

Added files:

Index: src/sys/arch/x86/x86/cpu_ucode_intel.c
diff -u /dev/null src/sys/arch/x86/x86/cpu_ucode_intel.c:1.1
--- /dev/null	Wed Aug 29 17:13:23 2012
+++ src/sys/arch/x86/x86/cpu_ucode_intel.c	Wed Aug 29 17:13:22 2012
@@ -0,0 +1,152 @@
+/* $NetBSD: cpu_ucode_intel.c,v 1.1 2012/08/29 17:13:22 drochner Exp $ */
+/*
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Drochner.
+ *
+ * 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_intel.c,v 1.1 2012/08/29 17:13:22 drochner 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>
+
+#define MSR_IA32_PLATFORM_ID 0x17
+#define MSR_IA32_BIOS_UPDT_TRIGGER 0x79
+#define MSR_IA32_BIOS_SIGN_ID 0x8b
+
+static void
+intel_getcurrentucode(uint32_t *ucodeversion, int *platformid)
+{
+	unsigned int unneeded_ids[4];
+	uint64_t msr;
+
+	kpreempt_disable();
+
+	wrmsr(MSR_IA32_BIOS_SIGN_ID, 0);
+	x86_cpuid(0, unneeded_ids);
+	msr = rdmsr(MSR_IA32_BIOS_SIGN_ID);
+	*ucodeversion = msr >> 32;
+
+	kpreempt_enable();
+
+	msr = rdmsr(MSR_IA32_PLATFORM_ID);
+	*platformid = ((int)(msr >> 50)) & 7;
+}
+
+int
+cpu_ucode_intel_get_version(struct cpu_ucode_version *ucode)
+{
+	struct cpu_info *ci = curcpu();
+	struct cpu_ucode_version_intel1 data;
+
+	if (ucode->loader_version != CPU_UCODE_LOADER_INTEL1 ||
+	    CPUID2FAMILY(ci->ci_signature) < 6)
+		return EOPNOTSUPP;
+	if (!ucode->data)
+		return 0;
+
+	intel_getcurrentucode(&data.ucodeversion, &data.platformid);
+
+	return copyout(&data, ucode->data, sizeof(data));
+}
+
+int
+cpu_ucode_intel_firmware_open(firmware_handle_t *fwh, const char *fwname)
+{
+	const char *fw_path = "cpu_x86_intel1";
+	uint32_t ucodeversion, cpu_signature;
+	int platformid;
+	char cpuspec[11];
+
+	if (fwname != NULL && fwname[0] != '\0')
+		return firmware_open(fw_path, fwname, fwh);
+
+	cpu_signature = curcpu()->ci_signature;
+	if (CPUID2FAMILY(cpu_signature) < 6)
+		return EOPNOTSUPP;
+
+	intel_getcurrentucode(&ucodeversion, &platformid);
+	sprintf(cpuspec, "%08x-%d", cpu_signature, platformid);
+
+	return firmware_open(fw_path, cpuspec, fwh);
+}
+
+#ifndef XEN
+int
+cpu_ucode_intel_apply(struct cpu_ucode_softc *sc, int cpuno)
+{
+	uint32_t ucodetarget, oucodeversion, nucodeversion;
+	int platformid;
+	struct intel1_ucode_header *uh;
+
+	if (sc->loader_version != CPU_UCODE_LOADER_INTEL1
+	    || cpuno != CPU_UCODE_CURRENT_CPU)
+		return EINVAL;
+
+	/* XXX relies on malloc alignment */
+	if ((uintptr_t)(sc->sc_blob) & 15) {
+		printf("ucode alignment bad\n");
+		return EINVAL;
+	}
+
+	uh = (struct intel1_ucode_header *)(sc->sc_blob);
+	if (uh->uh_header_ver != 1 || uh->uh_loader_rev != 1)
+		return EINVAL;
+	ucodetarget = uh->uh_rev;
+
+	kpreempt_disable();
+
+	intel_getcurrentucode(&oucodeversion, &platformid);
+	if (oucodeversion >= ucodetarget) {
+		kpreempt_enable();
+		return EEXIST; /* ??? */
+	}
+	wrmsr(MSR_IA32_BIOS_UPDT_TRIGGER, (uintptr_t)(sc->sc_blob) + 48);
+	intel_getcurrentucode(&nucodeversion, &platformid);
+
+	kpreempt_enable();
+
+	if (nucodeversion != ucodetarget)
+		return EIO;
+
+	printf("cpu %d: ucode 0x%x->0x%x\n", curcpu()->ci_index,
+	       oucodeversion, nucodeversion);
+
+	return 0;
+}
+#endif

Index: src/sys/compat/sys/cpuio.h
diff -u /dev/null src/sys/compat/sys/cpuio.h:1.4
--- /dev/null	Wed Aug 29 17:13:23 2012
+++ src/sys/compat/sys/cpuio.h	Wed Aug 29 17:13:22 2012
@@ -0,0 +1,9 @@
+/* $NetBSD: cpuio.h,v 1.4 2012/08/29 17:13:22 drochner Exp $ */
+
+struct compat6_cpu_ucode {
+	uint64_t version;
+	char fwname[PATH_MAX];
+};
+
+#define OIOC_CPU_UCODE_GET_VERSION      _IOR('c', 4, struct compat6_cpu_ucode)
+#define OIOC_CPU_UCODE_APPLY            _IOW('c', 5, struct compat6_cpu_ucode)

Reply via email to