diff options
| -rw-r--r-- | arch/x86/include/asm/fpu/xstate.h | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/fpu/core.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/fpu/init.c | 22 | ||||
| -rw-r--r-- | arch/x86/lib/delay.c | 2 | ||||
| -rw-r--r-- | arch/x86/platform/efi/quirks.c | 79 |
5 files changed, 79 insertions, 37 deletions
diff --git a/arch/x86/include/asm/fpu/xstate.h b/arch/x86/include/asm/fpu/xstate.h index af30fdeb140d..f23cd8c80b1c 100644 --- a/arch/x86/include/asm/fpu/xstate.h +++ b/arch/x86/include/asm/fpu/xstate.h | |||
| @@ -20,16 +20,15 @@ | |||
| 20 | 20 | ||
| 21 | /* Supported features which support lazy state saving */ | 21 | /* Supported features which support lazy state saving */ |
| 22 | #define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ | 22 | #define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ |
| 23 | XFEATURE_MASK_SSE) | 23 | XFEATURE_MASK_SSE | \ |
| 24 | |||
| 25 | /* Supported features which require eager state saving */ | ||
| 26 | #define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | \ | ||
| 27 | XFEATURE_MASK_BNDCSR | \ | ||
| 28 | XFEATURE_MASK_YMM | \ | 24 | XFEATURE_MASK_YMM | \ |
| 29 | XFEATURE_MASK_OPMASK | \ | 25 | XFEATURE_MASK_OPMASK | \ |
| 30 | XFEATURE_MASK_ZMM_Hi256 | \ | 26 | XFEATURE_MASK_ZMM_Hi256 | \ |
| 31 | XFEATURE_MASK_Hi16_ZMM) | 27 | XFEATURE_MASK_Hi16_ZMM) |
| 32 | 28 | ||
| 29 | /* Supported features which require eager state saving */ | ||
| 30 | #define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR) | ||
| 31 | |||
| 33 | /* All currently supported features */ | 32 | /* All currently supported features */ |
| 34 | #define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER) | 33 | #define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER) |
| 35 | 34 | ||
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index d25097c3fc1d..d5804adfa6da 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c | |||
| @@ -409,8 +409,10 @@ static inline void copy_init_fpstate_to_fpregs(void) | |||
| 409 | { | 409 | { |
| 410 | if (use_xsave()) | 410 | if (use_xsave()) |
| 411 | copy_kernel_to_xregs(&init_fpstate.xsave, -1); | 411 | copy_kernel_to_xregs(&init_fpstate.xsave, -1); |
| 412 | else | 412 | else if (static_cpu_has(X86_FEATURE_FXSR)) |
| 413 | copy_kernel_to_fxregs(&init_fpstate.fxsave); | 413 | copy_kernel_to_fxregs(&init_fpstate.fxsave); |
| 414 | else | ||
| 415 | copy_kernel_to_fregs(&init_fpstate.fsave); | ||
| 414 | } | 416 | } |
| 415 | 417 | ||
| 416 | /* | 418 | /* |
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 6d9f0a7ef4c8..bd08fb77073d 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c | |||
| @@ -78,13 +78,15 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c) | |||
| 78 | cr0 &= ~(X86_CR0_TS | X86_CR0_EM); | 78 | cr0 &= ~(X86_CR0_TS | X86_CR0_EM); |
| 79 | write_cr0(cr0); | 79 | write_cr0(cr0); |
| 80 | 80 | ||
| 81 | asm volatile("fninit ; fnstsw %0 ; fnstcw %1" | 81 | if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) { |
| 82 | : "+m" (fsw), "+m" (fcw)); | 82 | asm volatile("fninit ; fnstsw %0 ; fnstcw %1" |
| 83 | : "+m" (fsw), "+m" (fcw)); | ||
| 83 | 84 | ||
| 84 | if (fsw == 0 && (fcw & 0x103f) == 0x003f) | 85 | if (fsw == 0 && (fcw & 0x103f) == 0x003f) |
| 85 | set_cpu_cap(c, X86_FEATURE_FPU); | 86 | set_cpu_cap(c, X86_FEATURE_FPU); |
| 86 | else | 87 | else |
| 87 | clear_cpu_cap(c, X86_FEATURE_FPU); | 88 | clear_cpu_cap(c, X86_FEATURE_FPU); |
| 89 | } | ||
| 88 | 90 | ||
| 89 | #ifndef CONFIG_MATH_EMULATION | 91 | #ifndef CONFIG_MATH_EMULATION |
| 90 | if (!cpu_has_fpu) { | 92 | if (!cpu_has_fpu) { |
| @@ -132,7 +134,7 @@ static void __init fpu__init_system_generic(void) | |||
| 132 | * Set up the legacy init FPU context. (xstate init might overwrite this | 134 | * Set up the legacy init FPU context. (xstate init might overwrite this |
| 133 | * with a more modern format, if the CPU supports it.) | 135 | * with a more modern format, if the CPU supports it.) |
| 134 | */ | 136 | */ |
| 135 | fpstate_init_fxstate(&init_fpstate.fxsave); | 137 | fpstate_init(&init_fpstate); |
| 136 | 138 | ||
| 137 | fpu__init_system_mxcsr(); | 139 | fpu__init_system_mxcsr(); |
| 138 | } | 140 | } |
| @@ -300,12 +302,6 @@ u64 __init fpu__get_supported_xfeatures_mask(void) | |||
| 300 | static void __init fpu__clear_eager_fpu_features(void) | 302 | static void __init fpu__clear_eager_fpu_features(void) |
| 301 | { | 303 | { |
| 302 | setup_clear_cpu_cap(X86_FEATURE_MPX); | 304 | setup_clear_cpu_cap(X86_FEATURE_MPX); |
| 303 | setup_clear_cpu_cap(X86_FEATURE_AVX); | ||
| 304 | setup_clear_cpu_cap(X86_FEATURE_AVX2); | ||
| 305 | setup_clear_cpu_cap(X86_FEATURE_AVX512F); | ||
| 306 | setup_clear_cpu_cap(X86_FEATURE_AVX512PF); | ||
| 307 | setup_clear_cpu_cap(X86_FEATURE_AVX512ER); | ||
| 308 | setup_clear_cpu_cap(X86_FEATURE_AVX512CD); | ||
| 309 | } | 305 | } |
| 310 | 306 | ||
| 311 | /* | 307 | /* |
diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index e912b2f6d36e..2f07c291dcc8 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c | |||
| @@ -102,7 +102,7 @@ static void delay_mwaitx(unsigned long __loops) | |||
| 102 | * Use cpu_tss as a cacheline-aligned, seldomly | 102 | * Use cpu_tss as a cacheline-aligned, seldomly |
| 103 | * accessed per-cpu variable as the monitor target. | 103 | * accessed per-cpu variable as the monitor target. |
| 104 | */ | 104 | */ |
| 105 | __monitorx(this_cpu_ptr(&cpu_tss), 0, 0); | 105 | __monitorx(raw_cpu_ptr(&cpu_tss), 0, 0); |
| 106 | 106 | ||
| 107 | /* | 107 | /* |
| 108 | * AMD, like Intel, supports the EAX hint and EAX=0xf | 108 | * AMD, like Intel, supports the EAX hint and EAX=0xf |
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 2d66db8f80f9..ed30e79347e8 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c | |||
| @@ -131,6 +131,27 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size) | |||
| 131 | EXPORT_SYMBOL_GPL(efi_query_variable_store); | 131 | EXPORT_SYMBOL_GPL(efi_query_variable_store); |
| 132 | 132 | ||
| 133 | /* | 133 | /* |
| 134 | * Helper function for efi_reserve_boot_services() to figure out if we | ||
| 135 | * can free regions in efi_free_boot_services(). | ||
| 136 | * | ||
| 137 | * Use this function to ensure we do not free regions owned by somebody | ||
| 138 | * else. We must only reserve (and then free) regions: | ||
| 139 | * | ||
| 140 | * - Not within any part of the kernel | ||
| 141 | * - Not the BIOS reserved area (E820_RESERVED, E820_NVS, etc) | ||
| 142 | */ | ||
| 143 | static bool can_free_region(u64 start, u64 size) | ||
| 144 | { | ||
| 145 | if (start + size > __pa_symbol(_text) && start <= __pa_symbol(_end)) | ||
| 146 | return false; | ||
| 147 | |||
| 148 | if (!e820_all_mapped(start, start+size, E820_RAM)) | ||
| 149 | return false; | ||
| 150 | |||
| 151 | return true; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 134 | * The UEFI specification makes it clear that the operating system is free to do | 155 | * The UEFI specification makes it clear that the operating system is free to do |
| 135 | * whatever it wants with boot services code after ExitBootServices() has been | 156 | * whatever it wants with boot services code after ExitBootServices() has been |
| 136 | * called. Ignoring this recommendation a significant bunch of EFI implementations | 157 | * called. Ignoring this recommendation a significant bunch of EFI implementations |
| @@ -147,26 +168,50 @@ void __init efi_reserve_boot_services(void) | |||
| 147 | efi_memory_desc_t *md = p; | 168 | efi_memory_desc_t *md = p; |
| 148 | u64 start = md->phys_addr; | 169 | u64 start = md->phys_addr; |
| 149 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | 170 | u64 size = md->num_pages << EFI_PAGE_SHIFT; |
| 171 | bool already_reserved; | ||
| 150 | 172 | ||
| 151 | if (md->type != EFI_BOOT_SERVICES_CODE && | 173 | if (md->type != EFI_BOOT_SERVICES_CODE && |
| 152 | md->type != EFI_BOOT_SERVICES_DATA) | 174 | md->type != EFI_BOOT_SERVICES_DATA) |
| 153 | continue; | 175 | continue; |
| 154 | /* Only reserve where possible: | 176 | |
| 155 | * - Not within any already allocated areas | 177 | already_reserved = memblock_is_region_reserved(start, size); |
| 156 | * - Not over any memory area (really needed, if above?) | 178 | |
| 157 | * - Not within any part of the kernel | 179 | /* |
| 158 | * - Not the bios reserved area | 180 | * Because the following memblock_reserve() is paired |
| 159 | */ | 181 | * with free_bootmem_late() for this region in |
| 160 | if ((start + size > __pa_symbol(_text) | 182 | * efi_free_boot_services(), we must be extremely |
| 161 | && start <= __pa_symbol(_end)) || | 183 | * careful not to reserve, and subsequently free, |
| 162 | !e820_all_mapped(start, start+size, E820_RAM) || | 184 | * critical regions of memory (like the kernel image) or |
| 163 | memblock_is_region_reserved(start, size)) { | 185 | * those regions that somebody else has already |
| 164 | /* Could not reserve, skip it */ | 186 | * reserved. |
| 165 | md->num_pages = 0; | 187 | * |
| 166 | memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n", | 188 | * A good example of a critical region that must not be |
| 167 | start, start+size-1); | 189 | * freed is page zero (first 4Kb of memory), which may |
| 168 | } else | 190 | * contain boot services code/data but is marked |
| 191 | * E820_RESERVED by trim_bios_range(). | ||
| 192 | */ | ||
| 193 | if (!already_reserved) { | ||
| 169 | memblock_reserve(start, size); | 194 | memblock_reserve(start, size); |
| 195 | |||
| 196 | /* | ||
| 197 | * If we are the first to reserve the region, no | ||
| 198 | * one else cares about it. We own it and can | ||
| 199 | * free it later. | ||
| 200 | */ | ||
| 201 | if (can_free_region(start, size)) | ||
| 202 | continue; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* | ||
| 206 | * We don't own the region. We must not free it. | ||
| 207 | * | ||
| 208 | * Setting this bit for a boot services region really | ||
| 209 | * doesn't make sense as far as the firmware is | ||
| 210 | * concerned, but it does provide us with a way to tag | ||
| 211 | * those regions that must not be paired with | ||
| 212 | * free_bootmem_late(). | ||
| 213 | */ | ||
| 214 | md->attribute |= EFI_MEMORY_RUNTIME; | ||
| 170 | } | 215 | } |
| 171 | } | 216 | } |
| 172 | 217 | ||
| @@ -183,8 +228,8 @@ void __init efi_free_boot_services(void) | |||
| 183 | md->type != EFI_BOOT_SERVICES_DATA) | 228 | md->type != EFI_BOOT_SERVICES_DATA) |
| 184 | continue; | 229 | continue; |
| 185 | 230 | ||
| 186 | /* Could not reserve boot area */ | 231 | /* Do not free, someone else owns it: */ |
| 187 | if (!size) | 232 | if (md->attribute & EFI_MEMORY_RUNTIME) |
| 188 | continue; | 233 | continue; |
| 189 | 234 | ||
| 190 | free_bootmem_late(start, size); | 235 | free_bootmem_late(start, size); |
