the CPUs identified and then we had to update the CPU flags afterwards.
As microcode updates can add/remove instructions and features, we need
to load it earlier. Thus, make the bootloader look for the microcode
and supply it to the kernel as another bootarg. This way we can update
the cores' microcode before we identify them.
ok deraadt@
-/* $OpenBSD: cpu.c,v 1.110 2018/01/12 20:14:20 deraadt Exp $ */
+/* $OpenBSD: cpu.c,v 1.111 2018/02/06 01:09:17 patrick Exp $ */
/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
/*-
printf("(uniprocessor)\n");
ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY;
cpu_intr_init(ci);
+#ifndef SMALL_KERNEL
+ cpu_ucode_apply(ci);
+#endif
identifycpu(ci);
#ifdef MTRR
mem_range_attach();
#endif /* MTRR */
cpu_init(ci);
cpu_init_mwait(sc);
-#ifndef SMALL_KERNEL
- config_mountroot(NULL, cpu_ucode_attachhook);
-#endif
break;
case CPU_ROLE_BP:
printf("apid %d (boot processor)\n", caa->cpu_apicid);
ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY;
cpu_intr_init(ci);
+#ifndef SMALL_KERNEL
+ cpu_ucode_apply(ci);
+#endif
identifycpu(ci);
#ifdef MTRR
mem_range_attach();
ioapic_bsp_id = caa->cpu_apicid;
#endif
cpu_init_mwait(sc);
-#ifndef SMALL_KERNEL
- config_mountroot(NULL, cpu_ucode_attachhook);
-#endif
break;
case CPU_ROLE_AP:
lapic_enable();
lapic_startclock();
+ cpu_ucode_apply(ci);
if ((ci->ci_flags & CPUF_IDENTIFIED) == 0) {
/*
lldt(0);
cpu_init(ci);
- cpu_ucode_apply(ci);
- cpu_flags_update(ci);
#if NPVBUS > 0
pvbus_init_cpu();
#endif
return (0);
}
-
-void
-cpu_flags_update(struct cpu_info *ci)
-{
- uint32_t dummy;
-
- /* XXX this update is much later than we want it to be */
- if (cpuid_level >= 0x07) {
- CPUID_LEAF(0x7, 0, dummy, dummy, dummy,
- ci->ci_feature_sefflags_edx);
- }
- if (!strcmp(cpu_vendor, "AuthenticAMD") &&
- ci->ci_pnfeatset >= 0x80000008) {
- CPUID(0x80000008, dummy, ci->ci_feature_amdspec_ebx,
- dummy, dummy);
- }
-}
-/* $OpenBSD: machdep.c,v 1.237 2018/01/06 22:03:12 guenther Exp $ */
+/* $OpenBSD: machdep.c,v 1.238 2018/02/06 01:09:17 patrick Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
bios_memmap_t *bios_memmap;
u_int32_t bios_cksumlen;
bios_efiinfo_t *bios_efiinfo;
+bios_ucode_t *bios_ucode;
/*
* Size of memory segments, before any memory is stolen.
/* Safe for i/o port / memory space allocation to use malloc now. */
x86_bus_space_mallocok();
+
+#ifndef SMALL_KERNEL
+ cpu_ucode_setup();
+#endif
}
/*
docninit++;
break;
+ case BOOTARG_UCODE:
+ bios_ucode = (bios_ucode_t *)q->ba_arg;
+ break;
+
default:
#ifdef BOOTINFO_DEBUG
printf(" unsupported arg (%d) %p", q->ba_type,
-/* $OpenBSD: ucode.c,v 1.3 2018/01/14 20:15:37 bluhm Exp $ */
+/* $OpenBSD: ucode.c,v 1.4 2018/02/06 01:09:17 patrick Exp $ */
/*
* Copyright (c) 2018 Stefan Fritsch <fritsch@genua.de>
* Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mutex.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
+#include <machine/biosvar.h>
/* #define UCODE_DEBUG */
#ifdef UCODE_DEBUG
char * cpu_ucode_data;
size_t cpu_ucode_size;
-void cpu_ucode_setup(struct cpu_info *);
+void cpu_ucode_setup(void);
void cpu_ucode_apply(struct cpu_info *);
/* Intel */
struct mutex cpu_ucode_intel_mtx = MUTEX_INITIALIZER(IPL_HIGH);
void
-cpu_ucode_attachhook(struct device *dv)
+cpu_ucode_setup(void)
{
- struct cpu_info *ci = curcpu();
-
- cpu_ucode_setup(ci);
- cpu_ucode_apply(ci);
- cpu_flags_update(ci);
-}
-
-void
-cpu_ucode_setup(struct cpu_info *ci)
-{
- char name[128];
- u_char *ucode;
- size_t size;
-
- snprintf(name, sizeof(name), "intel/%02x-%02x-%02x", ci->ci_family,
- ci->ci_model, (ci->ci_signature >> 0) & 0x0f);
+ if (bios_ucode == NULL)
+ return;
- if (loadfirmware(name, &ucode, &size) != 0) {
- DPRINTF(("%s: no microcode found: %s\n", __func__, name));
+ if (!bios_ucode->uc_addr || !bios_ucode->uc_size)
return;
- }
- cpu_ucode_data = ucode;
- cpu_ucode_size = size;
+ cpu_ucode_size = bios_ucode->uc_size;
+ cpu_ucode_data = malloc(cpu_ucode_size, M_DEVBUF, M_WAITOK);
+ memcpy(cpu_ucode_data, (void *)PMAP_DIRECT_MAP(bios_ucode->uc_addr),
+ cpu_ucode_size);
}
/*
uint32_t old_rev, new_rev;
paddr_t data;
- if (cpu_ucode_data == NULL || cpu_ucode_size == 0)
+ if (cpu_ucode_data == NULL || cpu_ucode_size == 0) {
+ DPRINTF(("%s: no microcode provided\n", __func__));
return;
+ }
/*
* Grab a mutex, because we are not allowed to run updates
if (update == NULL)
update = cpu_ucode_intel_find(cpu_ucode_data,
cpu_ucode_size, old_rev);
- if (update == NULL)
+ if (update == NULL) {
+ DPRINTF(("%s: no microcode update found\n", __func__));
goto out;
- if (update->update_revision == old_rev)
+ }
+ if (update->update_revision == old_rev) {
+ DPRINTF(("%s: microcode already up-to-date\n", __func__));
goto out;
+ }
/* Apply microcode. */
data = (paddr_t)update;
-/* $OpenBSD: biosvar.h,v 1.24 2017/06/20 12:39:20 tom Exp $ */
+/* $OpenBSD: biosvar.h,v 1.25 2018/02/06 01:09:17 patrick Exp $ */
/*
* Copyright (c) 1997-1999 Michael Shalayeff
uint32_t fb_reserved_mask;
} __packed bios_efiinfo_t;
+#define BOOTARG_UCODE 12
+typedef struct _bios_ucode {
+ uint64_t uc_addr;
+ uint64_t uc_size;
+} __packed bios_ucode_t;
+
#if defined(_KERNEL) || defined (_STANDALONE)
#ifdef _LOCORE
extern u_int bootapiver;
extern bios_memmap_t *bios_memmap;
extern bios_efiinfo_t *bios_efiinfo;
+extern bios_ucode_t *bios_ucode;
#endif /* _KERNEL */
#endif /* _LOCORE */
-/* $OpenBSD: cpufunc.h,v 1.22 2018/01/11 22:31:09 patrick Exp $ */
+/* $OpenBSD: cpufunc.h,v 1.23 2018/02/06 01:09:17 patrick Exp $ */
/* $NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $ */
/*-
}
void amd64_errata(struct cpu_info *);
-void cpu_flags_update(struct cpu_info *);
+void cpu_ucode_setup(void);
void cpu_ucode_apply(struct cpu_info *);
-void cpu_ucode_attachhook(struct device *);
#endif /* _KERNEL */
-/* $OpenBSD: conf.c,v 1.38 2017/09/08 05:36:51 deraadt Exp $ */
+/* $OpenBSD: conf.c,v 1.39 2018/02/06 01:09:17 patrick Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
#include <biosdev.h>
#include <dev/cons.h>
-const char version[] = "3.33";
+const char version[] = "3.34";
int debug = 1;
-/* $OpenBSD: conf.c,v 1.33 2017/09/08 05:36:51 deraadt Exp $ */
+/* $OpenBSD: conf.c,v 1.34 2018/02/06 01:09:17 patrick Exp $ */
/*
* Copyright (c) 2004 Tom Cosgrove
#include <biosdev.h>
#include <dev/cons.h>
-const char version[] = "3.28";
+const char version[] = "3.29";
int debug = 1;
-/* $OpenBSD: conf.c,v 1.13 2018/01/30 20:19:06 naddy Exp $ */
+/* $OpenBSD: conf.c,v 1.14 2018/02/06 01:09:17 patrick Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
#include "efidev.h"
#include "efipxe.h"
-const char version[] = "3.37";
+const char version[] = "3.38";
#ifdef EFI_DEBUG
int debug = 0;
-/* $OpenBSD: exec_i386.c,v 1.19 2017/07/06 11:27:56 mlarkin Exp $ */
+/* $OpenBSD: exec_i386.c,v 1.20 2018/02/06 01:09:17 patrick Exp $ */
/*
* Copyright (c) 1997-1998 Michael Shalayeff
#include <dev/cons.h>
#include <lib/libsa/loadfile.h>
#include <machine/biosvar.h>
+#include <machine/specialreg.h>
#include <stand/boot/bootarg.h>
+#include "cmd.h"
#include "disk.h"
#include "libsa.h"
typedef void (*startfuncp)(int, int, int, int, int, int, int, int)
__attribute__ ((noreturn));
+void ucode_load(void);
+extern struct cmd_state cmd;
+
char *bootmac = NULL;
void
bcopy(bootdev_dip->disklabel.d_uid, &bootduid.duid, sizeof(bootduid));
addbootarg(BOOTARG_BOOTDUID, sizeof(bootduid), &bootduid);
+ ucode_load();
+
#ifdef SOFTRAID
if (bootdev_dip->sr_vol != NULL) {
bv = bootdev_dip->sr_vol;
#endif
/* not reached */
}
+
+void
+ucode_load(void)
+{
+ uint32_t model, family, stepping;
+ uint32_t dummy, signature;
+ uint32_t vendor[4];
+ bios_ucode_t uc;
+ struct stat sb;
+ char path[128];
+ size_t buflen;
+ char *buf;
+ int fd;
+
+ CPUID(0, dummy, vendor[0], vendor[2], vendor[1]);
+ vendor[3] = 0; /* NULL-terminate */
+ if (strcmp((char *)vendor, "GenuineIntel") != 0)
+ return;
+
+ CPUID(1, signature, dummy, dummy, dummy);
+ family = (signature >> 8) & 0x0f;
+ model = (signature >> 4) & 0x0f;
+ if (family == 0x6 || family == 0xf) {
+ family += (signature >> 20) & 0xff;
+ model += ((signature >> 16) & 0x0f) << 4;
+ }
+ stepping = (signature >> 0) & 0x0f;
+
+ snprintf(path, sizeof(path), "%s:/etc/firmware/intel/%02x-%02x-%02x",
+ cmd.bootdev, family, model, stepping);
+
+ fd = open(path, 0);
+ if (fd == -1)
+ return;
+
+ if (fstat(fd, &sb) == -1)
+ return;
+
+ buflen = sb.st_size;
+ if ((buf = alloc(buflen)) == NULL)
+ return;
+
+ if (read(fd, buf, buflen) != buflen) {
+ free(buf, buflen);
+ return;
+ }
+
+ uc.uc_addr = (uint64_t)buf;
+ uc.uc_size = (uint64_t)buflen;
+ addbootarg(BOOTARG_UCODE, sizeof(uc), &uc);
+}
-/* $OpenBSD: conf.c,v 1.37 2017/09/08 05:36:51 deraadt Exp $ */
+/* $OpenBSD: conf.c,v 1.38 2018/02/06 01:09:17 patrick Exp $ */
/*
* Copyright (c) 2004 Tom Cosgrove
#include "pxeboot.h"
#include "pxe_net.h"
-const char version[] = "3.28";
+const char version[] = "3.29";
int debug = 0;
void (*sa_cleanup)(void) = pxe_shutdown;