]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/x86/kernel/microcode_core_early.c
Merge remote-tracking branch 'tip/auto-latest'
[karo-tx-linux.git] / arch / x86 / kernel / microcode_core_early.c
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  */
44 static 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
60 static 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
75 void __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
99 void 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
123 int __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 }