Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  1/*
  2 *	X86 CPU microcode early update for Linux
  3 *
  4 *	Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
  5 *			   H Peter Anvin" <hpa@zytor.com>
  6 *
  7 *	This driver allows to early upgrade microcode on Intel processors
  8 *	belonging to IA-32 family - PentiumPro, Pentium II,
  9 *	Pentium III, Xeon, Pentium 4, etc.
 10 *
 11 *	Reference: Section 9.11 of Volume 3, IA-32 Intel Architecture
 12 *	Software Developer's Manual.
 13 *
 14 *	This program is free software; you can redistribute it and/or
 15 *	modify it under the terms of the GNU General Public License
 16 *	as published by the Free Software Foundation; either version
 17 *	2 of the License, or (at your option) any later version.
 18 */
 19#include <linux/module.h>
 20#include <asm/microcode_intel.h>
 21#include <asm/microcode_amd.h>
 22#include <asm/processor.h>
 23
 24#define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
 25#define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u')
 26#define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I')
 27#define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l')
 28#define CPUID_AMD1 QCHAR('A', 'u', 't', 'h')
 29#define CPUID_AMD2 QCHAR('e', 'n', 't', 'i')
 30#define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D')
 31
 32#define CPUID_IS(a, b, c, ebx, ecx, edx)	\
 33		(!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c))))
 34
 35/*
 36 * In early loading microcode phase on BSP, boot_cpu_data is not set up yet.
 37 * x86_vendor() gets vendor id for BSP.
 38 *
 39 * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify
 40 * coding, we still use x86_vendor() to get vendor id for AP.
 41 *
 42 * x86_vendor() gets vendor information directly through cpuid.
 43 */
 44static int x86_vendor(void)
 45{
 46	u32 eax = 0x00000000;
 47	u32 ebx, ecx = 0, edx;
 48
 49	native_cpuid(&eax, &ebx, &ecx, &edx);
 50
 51	if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx))
 52		return X86_VENDOR_INTEL;
 53
 54	if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx))
 55		return X86_VENDOR_AMD;
 56
 57	return X86_VENDOR_UNKNOWN;
 58}
 59
 60static int x86_family(void)
 61{
 62	u32 eax = 0x00000001;
 63	u32 ebx, ecx = 0, edx;
 64	int x86;
 65
 66	native_cpuid(&eax, &ebx, &ecx, &edx);
 67
 68	x86 = (eax >> 8) & 0xf;
 69	if (x86 == 15)
 70		x86 += (eax >> 20) & 0xff;
 71
 72	return x86;
 73}
 74
 75void __init load_ucode_bsp(void)
 76{
 77	int vendor, x86;
 78
 79	if (!have_cpuid_p())
 80		return;
 81
 82	vendor = x86_vendor();
 83	x86 = x86_family();
 84
 85	switch (vendor) {
 86	case X86_VENDOR_INTEL:
 87		if (x86 >= 6)
 88			load_ucode_intel_bsp();
 89		break;
 90	case X86_VENDOR_AMD:
 91		if (x86 >= 0x10)
 92			load_ucode_amd_bsp();
 93		break;
 94	default:
 95		break;
 96	}
 97}
 98
 99void load_ucode_ap(void)
100{
101	int vendor, x86;
102
103	if (!have_cpuid_p())
104		return;
105
106	vendor = x86_vendor();
107	x86 = x86_family();
108
109	switch (vendor) {
110	case X86_VENDOR_INTEL:
111		if (x86 >= 6)
112			load_ucode_intel_ap();
113		break;
114	case X86_VENDOR_AMD:
115		if (x86 >= 0x10)
116			load_ucode_amd_ap();
117		break;
118	default:
119		break;
120	}
121}
122
123int __init save_microcode_in_initrd(void)
124{
125	struct cpuinfo_x86 *c = &boot_cpu_data;
126
127	switch (c->x86_vendor) {
128	case X86_VENDOR_INTEL:
129		if (c->x86 >= 6)
130			save_microcode_in_initrd_intel();
131		break;
132	case X86_VENDOR_AMD:
133		if (c->x86 >= 0x10)
134			save_microcode_in_initrd_amd();
135		break;
136	default:
137		break;
138	}
139
140	return 0;
141}