diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/xen/enlighten.c | 50 |
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 | ||
171 | static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; | ||
172 | static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; | ||
173 | |||
171 | static void xen_cpuid(unsigned int *ax, unsigned int *bx, | 174 | static 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 | ||
200 | static __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 | |||
196 | static void xen_set_debugreg(int reg, unsigned long val) | 232 | static 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. |