aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/xen/enlighten.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 5d9a1c37c515..69de19168a7e 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -168,21 +168,23 @@ static void __init xen_banner(void)
168 xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); 168 xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
169} 169}
170 170
171static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
172static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
173
171static void xen_cpuid(unsigned int *ax, unsigned int *bx, 174static void xen_cpuid(unsigned int *ax, unsigned int *bx,
172 unsigned int *cx, unsigned int *dx) 175 unsigned int *cx, unsigned int *dx)
173{ 176{
177 unsigned maskecx = ~0;
174 unsigned maskedx = ~0; 178 unsigned maskedx = ~0;
175 179
176 /* 180 /*
177 * Mask out inconvenient features, to try and disable as many 181 * Mask out inconvenient features, to try and disable as many
178 * unsupported kernel subsystems as possible. 182 * unsupported kernel subsystems as possible.
179 */ 183 */
180 if (*ax == 1) 184 if (*ax == 1) {
181 maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */ 185 maskecx = cpuid_leaf1_ecx_mask;
182 (1 << X86_FEATURE_ACPI) | /* disable ACPI */ 186 maskedx = cpuid_leaf1_edx_mask;
183 (1 << X86_FEATURE_MCE) | /* disable MCE */ 187 }
184 (1 << X86_FEATURE_MCA) | /* disable MCA */
185 (1 << X86_FEATURE_ACC)); /* thermal monitoring */
186 188
187 asm(XEN_EMULATE_PREFIX "cpuid" 189 asm(XEN_EMULATE_PREFIX "cpuid"
188 : "=a" (*ax), 190 : "=a" (*ax),
@@ -190,9 +192,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
190 "=c" (*cx), 192 "=c" (*cx),
191 "=d" (*dx) 193 "=d" (*dx)
192 : "0" (*ax), "2" (*cx)); 194 : "0" (*ax), "2" (*cx));
195
196 *cx &= maskecx;
193 *dx &= maskedx; 197 *dx &= maskedx;
194} 198}
195 199
200static __init void xen_init_cpuid_mask(void)
201{
202 unsigned int ax, bx, cx, dx;
203
204 cpuid_leaf1_edx_mask =
205 ~((1 << X86_FEATURE_MCE) | /* disable MCE */
206 (1 << X86_FEATURE_MCA) | /* disable MCA */
207 (1 << X86_FEATURE_ACC)); /* thermal monitoring */
208
209 if (!xen_initial_domain())
210 cpuid_leaf1_edx_mask &=
211 ~((1 << X86_FEATURE_APIC) | /* disable local APIC */
212 (1 << X86_FEATURE_ACPI)); /* disable ACPI */
213
214 ax = 1;
215 xen_cpuid(&ax, &bx, &cx, &dx);
216
217 /* cpuid claims we support xsave; try enabling it to see what happens */
218 if (cx & (1 << (X86_FEATURE_XSAVE % 32))) {
219 unsigned long cr4;
220
221 set_in_cr4(X86_CR4_OSXSAVE);
222
223 cr4 = read_cr4();
224
225 if ((cr4 & X86_CR4_OSXSAVE) == 0)
226 cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32));
227
228 clear_in_cr4(X86_CR4_OSXSAVE);
229 }
230}
231
196static void xen_set_debugreg(int reg, unsigned long val) 232static void xen_set_debugreg(int reg, unsigned long val)
197{ 233{
198 HYPERVISOR_set_debugreg(reg, val); 234 HYPERVISOR_set_debugreg(reg, val);
@@ -903,6 +939,8 @@ asmlinkage void __init xen_start_kernel(void)
903 939
904 xen_init_irq_ops(); 940 xen_init_irq_ops();
905 941
942 xen_init_cpuid_mask();
943
906#ifdef CONFIG_X86_LOCAL_APIC 944#ifdef CONFIG_X86_LOCAL_APIC
907 /* 945 /*
908 * set up the basic apic ops. 946 * set up the basic apic ops.