1/* $NetBSD: $ */
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: $");
33
34#include "opt_cpu_ucode.h"
35
36#include <sys/param.h>
37#include <sys/cpuio.h>
38#include <sys/cpu.h>
39
40#include <dev/firmload.h>
41
42#include <machine/cpuvar.h>
43#include <machine/cputypes.h>
44
45#include <x86/cpu_ucode.h>
46
47static struct cpu_ucode_softc ucode_softc;
48
49int
50cpu_ucode_get_version(void *data)
51{
52	struct cpu_ucode *ucode = data;
53
54	switch (cpu_vendor) {
55	case CPUVENDOR_AMD:
56		return cpu_ucode_amd_get_version(ucode);
57	default:
58		ucode->version = (uint64_t)-1;
59		return EOPNOTSUPP;
60	}
61
62	return 0;
63}
64
65int
66cpu_ucode_md_open(firmware_handle_t *fwh, const char *fwname)
67{
68	switch (cpu_vendor) {
69	case CPUVENDOR_AMD:
70		return cpu_ucode_amd_firmware_open(fwh, fwname);
71	case CPUVENDOR_INTEL:
72		return EOPNOTSUPP; /* not yet supported */
73	default:
74		return EOPNOTSUPP;
75	}
76}
77
78int
79cpu_ucode_apply(void *data)
80{
81	struct cpu_ucode *ucode = data;
82	struct cpu_ucode_softc *sc = &ucode_softc;
83	struct xen_platform_op op;
84	int error;
85
86	error = cpu_ucode_load(sc, ucode->fwname);
87	if (error)
88		return error;
89
90	op.cmd = XENPF_microcode_update;
91	set_xen_guest_handle(op.u.microcode.data, sc->sc_blob);
92	op.u.microcode.length = sc->sc_blobsize;
93
94	error = -HYPERVISOR_platform_op(&op);
95
96	if (sc->sc_blob)
97		firmware_free(sc->sc_blob, 0);
98	sc->sc_blob = NULL;
99	sc->sc_blobsize = 0;
100	return error;
101}
102