* Enable XSAVE if supported and allowed by user. * Calculate the xsave_mask. */
| 326 | * Calculate the xsave_mask. |
| 327 | */ |
| 328 | static void |
| 329 | fpuinit_bsp1(void) |
| 330 | { |
| 331 | u_int cp[4]; |
| 332 | uint64_t xsave_mask_user; |
| 333 | bool old_wp; |
| 334 | |
| 335 | if (!use_xsave) |
| 336 | return; |
| 337 | cpuid_count(0xd, 0x0, cp); |
| 338 | xsave_mask = XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE; |
| 339 | if ((cp[0] & xsave_mask) != xsave_mask) |
| 340 | panic("CPU0 does not support X87 or SSE: %x", cp[0]); |
| 341 | xsave_mask = ((uint64_t)cp[3] << 32) | cp[0]; |
| 342 | xsave_mask_user = xsave_mask; |
| 343 | TUNABLE_ULONG_FETCH("hw.xsave_mask", &xsave_mask_user); |
| 344 | xsave_mask_user |= XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE; |
| 345 | xsave_mask &= xsave_mask_user; |
| 346 | if ((xsave_mask & XFEATURE_AVX512) != XFEATURE_AVX512) |
| 347 | xsave_mask &= ~XFEATURE_AVX512; |
| 348 | if ((xsave_mask & XFEATURE_MPX) != XFEATURE_MPX) |
| 349 | xsave_mask &= ~XFEATURE_MPX; |
| 350 | |
| 351 | cpuid_count(0xd, 0x1, cp); |
| 352 | if ((cp[0] & CPUID_EXTSTATE_XSAVEOPT) != 0) { |
| 353 | /* |
| 354 | * Patch the XSAVE instruction in the cpu_switch code |
| 355 | * to XSAVEOPT. We assume that XSAVE encoding used |
| 356 | * REX byte, and set the bit 4 of the r/m byte. |
| 357 | * |
| 358 | * It seems that some BIOSes give control to the OS |
| 359 | * with CR0.WP already set, making the kernel text |
| 360 | * read-only before cpu_startup(). |
| 361 | */ |
| 362 | old_wp = disable_wp(); |
| 363 | ctx_switch_xsave32[3] |= 0x10; |
| 364 | ctx_switch_xsave[3] |= 0x10; |
| 365 | restore_wp(old_wp); |
| 366 | } |
| 367 | } |
| 368 | |
| 369 | /* |
| 370 | * Calculate the fpu save area size. |
no test coverage detected