Home | History | Annotate | Line # | Download | only in x86
cpu_ucode.c revision 1.13
      1 /* $NetBSD: cpu_ucode.c,v 1.13 2020/04/25 15:26:18 bouyer 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.13 2020/04/25 15:26:18 bouyer Exp $");
     33 
     34 #if defined(_KERNEL_OPT)
     35 #include "opt_cpu_ucode.h"
     36 #include "opt_xen.h"
     37 #endif
     38 
     39 #include <sys/param.h>
     40 #include <sys/cpuio.h>
     41 #include <sys/cpu.h>
     42 
     43 #include <dev/firmload.h>
     44 
     45 #include <machine/cpuvar.h>
     46 #include <machine/cputypes.h>
     47 
     48 #include <x86/cpu_ucode.h>
     49 
     50 #ifdef XEN
     51 #include <xen/include/public/xen.h>
     52 #include <xen/hypervisor.h>
     53 #endif
     54 
     55 static struct cpu_ucode_softc ucode_softc;
     56 
     57 int
     58 cpu_ucode_get_version(struct cpu_ucode_version *data)
     59 {
     60 	union {
     61 		struct cpu_ucode_version_amd a;
     62 		struct cpu_ucode_version_intel1 i;
     63 	} v;
     64 	size_t l;
     65 	int error;
     66 
     67 	if (!data->data)
     68 		return 0;
     69 
     70 	switch (cpu_vendor) {
     71 	case CPUVENDOR_AMD:
     72 		l = sizeof(v.a);
     73 		error = cpu_ucode_amd_get_version(data, &v, l);
     74 		break;
     75 	case CPUVENDOR_INTEL:
     76 		l = sizeof(v.i);
     77 		error = cpu_ucode_intel_get_version(data, &v, l);
     78 		break;
     79 	default:
     80 		return EOPNOTSUPP;
     81 	}
     82 
     83 	if (error)
     84 		return error;
     85 
     86 	return copyout(&v, data->data, l);
     87 }
     88 
     89 int
     90 cpu_ucode_md_open(firmware_handle_t *fwh, int loader_version, const char *fwname)
     91 {
     92 	switch (cpu_vendor) {
     93 	case CPUVENDOR_AMD:
     94 		return cpu_ucode_amd_firmware_open(fwh, fwname);
     95 	case CPUVENDOR_INTEL:
     96 		return cpu_ucode_intel_firmware_open(fwh, fwname);
     97 	default:
     98 		return EOPNOTSUPP;
     99 	}
    100 }
    101 
    102 #ifndef XENPV
    103 int
    104 cpu_ucode_apply(const struct cpu_ucode *data)
    105 {
    106 	struct cpu_ucode_softc *sc = &ucode_softc;
    107 	int error;
    108 
    109 	sc->loader_version = data->loader_version;
    110 
    111 	error = cpu_ucode_load(sc, data->fwname);
    112 	if (error)
    113 		return error;
    114 
    115 	switch (cpu_vendor) {
    116 	case CPUVENDOR_AMD:
    117 		error = cpu_ucode_amd_apply(sc, data->cpu_nr);
    118 		break;
    119 	case CPUVENDOR_INTEL:
    120 		error = cpu_ucode_intel_apply(sc, data->cpu_nr);
    121 		break;
    122 	default:
    123 		error = EOPNOTSUPP;
    124 	}
    125 
    126 	if (sc->sc_blob != NULL)
    127 		firmware_free(sc->sc_blob, sc->sc_blobsize);
    128 	sc->sc_blob = NULL;
    129 	sc->sc_blobsize = 0;
    130 	return error;
    131 }
    132 #else
    133 int
    134 cpu_ucode_apply(const struct cpu_ucode *data)
    135 {
    136 	struct cpu_ucode_softc *sc = &ucode_softc;
    137 	struct xen_platform_op op;
    138 	int error;
    139 
    140 	/* Xen updates all??? */
    141 	if (data->cpu_nr != CPU_UCODE_ALL_CPUS)
    142 		return EOPNOTSUPP;
    143 
    144 	sc->loader_version = data->loader_version;
    145 	error = cpu_ucode_load(sc, data->fwname);
    146 	if (error)
    147 		return error;
    148 
    149 	op.cmd = XENPF_microcode_update;
    150 	set_xen_guest_handle(op.u.microcode.data, sc->sc_blob);
    151 	op.u.microcode.length = sc->sc_blobsize;
    152 
    153 	error = -HYPERVISOR_platform_op(&op);
    154 
    155 	if (sc->sc_blob)
    156 		firmware_free(sc->sc_blob, sc->sc_blobsize);
    157 	sc->sc_blob = NULL;
    158 	sc->sc_blobsize = 0;
    159 	return error;
    160 }
    161 #endif /* XEN */
    162