mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-08 11:56:41 +07:00
x86/fpu: Introduce cpu_has_xfeatures(xfeatures_mask, feature_name)
A lot of FPU using driver code is querying complex CPU features to be able to figure out whether a given set of xstate features is supported by the CPU or not. Introduce a simplified API function that can be used on any CPU type to get this information. Also add an error string return pointer, so that the driver can print a meaningful error message with a standardized feature name. Also mark xfeatures_mask as __read_only. Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
6278485450
commit
5b07343034
@ -36,4 +36,13 @@ extern bool irq_fpu_usable(void);
|
||||
extern int irq_ts_save(void);
|
||||
extern void irq_ts_restore(int TS_state);
|
||||
|
||||
/*
|
||||
* Query the presence of one or more xfeatures. Works on any legacy CPU as well.
|
||||
*
|
||||
* If 'feature_name' is set then put a human-readable description of
|
||||
* the feature there as well - this can be used to print error (or success)
|
||||
* messages.
|
||||
*/
|
||||
extern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name);
|
||||
|
||||
#endif /* _ASM_X86_FPU_API_H */
|
||||
|
@ -11,10 +11,23 @@
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/xcr.h>
|
||||
|
||||
static const char *xfeature_names[] =
|
||||
{
|
||||
"x87 floating point registers" ,
|
||||
"SSE registers" ,
|
||||
"AVX registers" ,
|
||||
"MPX bounds registers" ,
|
||||
"MPX CSR" ,
|
||||
"AVX-512 opmask" ,
|
||||
"AVX-512 Hi256" ,
|
||||
"AVX-512 ZMM_Hi256" ,
|
||||
"unknown xstate feature" ,
|
||||
};
|
||||
|
||||
/*
|
||||
* Mask of xstate features supported by the CPU and the kernel:
|
||||
*/
|
||||
u64 xfeatures_mask;
|
||||
u64 xfeatures_mask __read_mostly;
|
||||
|
||||
/*
|
||||
* Represents init state for the supported extended state.
|
||||
@ -28,6 +41,44 @@ static unsigned int xstate_comp_offsets[sizeof(xfeatures_mask)*8];
|
||||
/* The number of supported xfeatures in xfeatures_mask: */
|
||||
static unsigned int xfeatures_nr;
|
||||
|
||||
/*
|
||||
* Return whether the system supports a given xfeature.
|
||||
*
|
||||
* Also return the name of the (most advanced) feature that the caller requested:
|
||||
*/
|
||||
int cpu_has_xfeatures(u64 xfeatures_needed, const char **feature_name)
|
||||
{
|
||||
u64 xfeatures_missing = xfeatures_needed & ~xfeatures_mask;
|
||||
|
||||
if (unlikely(feature_name)) {
|
||||
long xfeature_idx, max_idx;
|
||||
u64 xfeatures_print;
|
||||
/*
|
||||
* So we use FLS here to be able to print the most advanced
|
||||
* feature that was requested but is missing. So if a driver
|
||||
* asks about "XSTATE_SSE | XSTATE_YMM" we'll print the
|
||||
* missing AVX feature - this is the most informative message
|
||||
* to users:
|
||||
*/
|
||||
if (xfeatures_missing)
|
||||
xfeatures_print = xfeatures_missing;
|
||||
else
|
||||
xfeatures_print = xfeatures_needed;
|
||||
|
||||
xfeature_idx = fls64(xfeatures_print)-1;
|
||||
max_idx = ARRAY_SIZE(xfeature_names)-1;
|
||||
xfeature_idx = min(xfeature_idx, max_idx);
|
||||
|
||||
*feature_name = xfeature_names[xfeature_idx];
|
||||
}
|
||||
|
||||
if (xfeatures_missing)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpu_has_xfeatures);
|
||||
|
||||
/*
|
||||
* When executing XSAVEOPT (optimized XSAVE), if a processor implementation
|
||||
* detects that an FPU state component is still (or is again) in its
|
||||
|
Loading…
Reference in New Issue
Block a user