diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 7e69ce9a1c..c29b067070 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -72,6 +72,7 @@ allow dom0_t xen_t:xen2 { allow dom0_t xen_t:xen2 { pmu_ctrl get_symbol + get_cpu_levelling_caps }; # Allow dom0 to use all XENVER_ subops and VERSION subops that have checks. diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index b5c023f743..7ef75b08e5 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -36,6 +36,12 @@ integer_param("cpuid_mask_ext_ecx", opt_cpuid_mask_ext_ecx); unsigned int opt_cpuid_mask_ext_edx = ~0u; integer_param("cpuid_mask_ext_edx", opt_cpuid_mask_ext_edx); +unsigned int __initdata expected_levelling_cap; +unsigned int __read_mostly levelling_caps; + +DEFINE_PER_CPU(struct cpuidmasks, cpuidmasks); +struct cpuidmasks __read_mostly cpuidmask_defaults; + const struct cpu_dev *__read_mostly cpu_devs[X86_VENDOR_NUM] = {}; unsigned int paddr_bits __read_mostly = 36; diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 58cbd70c98..f68cbec15e 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -190,6 +190,12 @@ long arch_do_sysctl( } break; + case XEN_SYSCTL_get_cpu_levelling_caps: + sysctl->u.cpu_levelling_caps.caps = levelling_caps; + if ( __copy_field_to_guest(u_sysctl, sysctl, u.cpu_levelling_caps.caps) ) + ret = -EFAULT; + break; + default: ret = -ENOSYS; break; diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index 6a0857907a..9a93799414 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -83,6 +83,7 @@ #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) #define cpu_has_monitor boot_cpu_has(X86_FEATURE_MONITOR) #define cpu_has_eist boot_cpu_has(X86_FEATURE_EIST) +#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) enum _cache_type { CACHE_TYPE_NULL = 0, diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h index 4725672e60..9a21c25ec1 100644 --- a/xen/include/asm-x86/cpuid.h +++ b/xen/include/asm-x86/cpuid.h @@ -3,6 +3,7 @@ #include #include +#include #define FSCAPINTS FEATURESET_NR_ENTRIES @@ -18,6 +19,7 @@ #ifndef __ASSEMBLY__ #include +#include extern const uint32_t known_features[FSCAPINTS]; extern const uint32_t special_features[FSCAPINTS]; @@ -31,6 +33,36 @@ void calculate_featuresets(void); const uint32_t *lookup_deep_deps(uint32_t feature); +/* + * Expected levelling capabilities (given cpuid vendor/family information), + * and levelling capabilities actually available (given MSR probing). + */ +#define LCAP_faulting XEN_SYSCTL_CPU_LEVELCAP_faulting +#define LCAP_1cd (XEN_SYSCTL_CPU_LEVELCAP_ecx | \ + XEN_SYSCTL_CPU_LEVELCAP_edx) +#define LCAP_e1cd (XEN_SYSCTL_CPU_LEVELCAP_extd_ecx | \ + XEN_SYSCTL_CPU_LEVELCAP_extd_edx) +#define LCAP_Da1 XEN_SYSCTL_CPU_LEVELCAP_xsave_eax +#define LCAP_6c XEN_SYSCTL_CPU_LEVELCAP_thermal_ecx +#define LCAP_7ab0 (XEN_SYSCTL_CPU_LEVELCAP_l7s0_eax | \ + XEN_SYSCTL_CPU_LEVELCAP_l7s0_ebx) +extern unsigned int expected_levelling_cap, levelling_caps; + +struct cpuidmasks +{ + uint64_t _1cd; + uint64_t e1cd; + uint64_t Da1; + uint64_t _6c; + uint64_t _7ab0; +}; + +/* Per CPU shadows of masking MSR values, for lazy context switching. */ +DECLARE_PER_CPU(struct cpuidmasks, cpuidmasks); + +/* Default masking MSR values, calculated at boot. */ +extern struct cpuidmasks cpuidmask_defaults; + #endif /* __ASSEMBLY__ */ #endif /* !__X86_CPUID_H__ */ diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 96680ebec0..1ab16dbef3 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -766,6 +766,27 @@ struct xen_sysctl_tmem_op { typedef struct xen_sysctl_tmem_op xen_sysctl_tmem_op_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tmem_op_t); +/* + * XEN_SYSCTL_get_cpu_levelling_caps (x86 specific) + * + * Return hardware capabilities concerning masking or faulting of the cpuid + * instruction for PV guests. + */ +struct xen_sysctl_cpu_levelling_caps { +#define XEN_SYSCTL_CPU_LEVELCAP_faulting (1ul << 0) /* CPUID faulting */ +#define XEN_SYSCTL_CPU_LEVELCAP_ecx (1ul << 1) /* 0x00000001.ecx */ +#define XEN_SYSCTL_CPU_LEVELCAP_edx (1ul << 2) /* 0x00000001.edx */ +#define XEN_SYSCTL_CPU_LEVELCAP_extd_ecx (1ul << 3) /* 0x80000001.ecx */ +#define XEN_SYSCTL_CPU_LEVELCAP_extd_edx (1ul << 4) /* 0x80000001.edx */ +#define XEN_SYSCTL_CPU_LEVELCAP_xsave_eax (1ul << 5) /* 0x0000000D:1.eax */ +#define XEN_SYSCTL_CPU_LEVELCAP_thermal_ecx (1ul << 6) /* 0x00000006.ecx */ +#define XEN_SYSCTL_CPU_LEVELCAP_l7s0_eax (1ul << 7) /* 0x00000007:0.eax */ +#define XEN_SYSCTL_CPU_LEVELCAP_l7s0_ebx (1ul << 8) /* 0x00000007:0.ebx */ + uint32_t caps; +}; +typedef struct xen_sysctl_cpu_levelling_caps xen_sysctl_cpu_levelling_caps_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_levelling_caps_t); + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -791,6 +812,7 @@ struct xen_sysctl { #define XEN_SYSCTL_pcitopoinfo 22 #define XEN_SYSCTL_psr_cat_op 23 #define XEN_SYSCTL_tmem_op 24 +#define XEN_SYSCTL_get_cpu_levelling_caps 25 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -816,6 +838,7 @@ struct xen_sysctl { struct xen_sysctl_psr_cmt_op psr_cmt_op; struct xen_sysctl_psr_cat_op psr_cat_op; struct xen_sysctl_tmem_op tmem_op; + struct xen_sysctl_cpu_levelling_caps cpu_levelling_caps; uint8_t pad[128]; } u; }; diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 118c3e6cda..7f9d90d833 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -808,6 +808,9 @@ static int flask_sysctl(int cmd) case XEN_SYSCTL_tmem_op: return domain_has_xen(current->domain, XEN__TMEM_CONTROL); + case XEN_SYSCTL_get_cpu_levelling_caps: + return domain_has_xen(current->domain, XEN2__GET_CPU_LEVELLING_CAPS); + default: printk("flask_sysctl: Unknown op %d\n", cmd); return -EPERM; diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index 56600bba4d..31ecf0276e 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -93,6 +93,8 @@ class xen2 pmu_ctrl # PMU use (domains, including unprivileged ones, will be using this operation) pmu_use +# XEN_SYSCTL_get_cpu_levelling_caps + get_cpu_levelling_caps } # Classes domain and domain2 consist of operations that a domain performs on