|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 1/2] x86/xstate: Use a guests CPUID policy, rather than allowing all features
>>> On 27.07.18 at 11:37, <andrew.cooper3@xxxxxxxxxx> wrote:
> Before 4.9, the calls to {hvm,pv}_cpuid() are needed to because the
> information can't be read directly out of d->arch.cpuids[]. The restore
> boolean is needed because this array will be empty at the time it is
> accessed on the restore path.
Would you mind looking over the 4.8 backport below, where I think I've
got away without such a boolean?
Thanks, Jan
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1177,7 +1177,7 @@ long arch_do_domctl(
if ( _xcr0_accum )
{
if ( evc->size >= PV_XSAVE_HDR_SIZE + XSTATE_AREA_MIN_SIZE )
- ret = validate_xstate(_xcr0, _xcr0_accum,
+ ret = validate_xstate(d, _xcr0, _xcr0_accum,
&_xsave_area->xsave_hdr);
}
else if ( !_xcr0 )
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1356,7 +1356,7 @@ static int hvm_load_cpu_xsave_states(str
ctxt = (struct hvm_hw_cpu_xsave *)&h->data[h->cur];
h->cur += desc->length;
- err = validate_xstate(ctxt->xcr0, ctxt->xcr0_accum,
+ err = validate_xstate(d, ctxt->xcr0, ctxt->xcr0_accum,
(const void *)&ctxt->save_area.xsave_hdr);
if ( err )
{
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -652,12 +652,47 @@ static bool_t valid_xcr0(u64 xcr0)
return !(xcr0 & XSTATE_BNDREGS) == !(xcr0 & XSTATE_BNDCSR);
}
-int validate_xstate(u64 xcr0, u64 xcr0_accum, const struct xsave_hdr *hdr)
+static uint64_t guest_xcr0_max(const struct domain *d)
{
+ if ( has_hvm_container_domain(d) )
+ {
+ uint32_t eax, ecx = 0, edx;
+
+ hvm_cpuid(XSTATE_CPUID, &eax, NULL, &ecx, &edx);
+
+ return ((uint64_t)edx << 32) | eax;
+ }
+ else
+ {
+ struct cpu_user_regs regs = { };
+
+ regs._eax = XSTATE_CPUID;
+ regs._ecx = 0;
+ pv_cpuid(®s);
+
+ return (regs.rdx << 32) | regs._eax;
+ }
+}
+
+int validate_xstate(const struct domain *d, uint64_t xcr0, uint64_t xcr0_accum,
+ const struct xsave_hdr *hdr)
+{
+ uint64_t xcr0_max;
unsigned int i;
+ if ( d == current->domain )
+ xcr0_max = guest_xcr0_max(d);
+ else
+ {
+ xcr0_max = xfeature_mask;
+ if ( !has_hvm_container_domain(d) )
+ xcr0_max &= ~(XSTATE_BNDREGS | XSTATE_BNDCSR |
+ XSTATE_PKRU | XSTATE_LWP);
+ }
+
if ( (hdr->xstate_bv & ~xcr0_accum) ||
(xcr0 & ~xcr0_accum) ||
+ (xcr0_accum & ~xcr0_max) ||
!valid_xcr0(xcr0) ||
!valid_xcr0(xcr0_accum) )
return -EINVAL;
@@ -676,18 +711,16 @@ int validate_xstate(u64 xcr0, u64 xcr0_a
int handle_xsetbv(u32 index, u64 new_bv)
{
struct vcpu *curr = current;
+ uint64_t xcr0_max = guest_xcr0_max(curr->domain);
u64 mask;
if ( index != XCR_XFEATURE_ENABLED_MASK )
return -EOPNOTSUPP;
- if ( (new_bv & ~xfeature_mask) || !valid_xcr0(new_bv) )
+ if ( (new_bv & ~xcr0_max) ||
+ (new_bv & ~xfeature_mask) || !valid_xcr0(new_bv) )
return -EINVAL;
- /* XCR0.PKRU is disabled on PV mode. */
- if ( is_pv_vcpu(curr) && (new_bv & XSTATE_PKRU) )
- return -EOPNOTSUPP;
-
if ( !set_xcr0(new_bv) )
return -EFAULT;
--- a/xen/include/asm-x86/xstate.h
+++ b/xen/include/asm-x86/xstate.h
@@ -107,8 +107,9 @@ uint64_t get_msr_xss(void);
void xsave(struct vcpu *v, uint64_t mask);
void xrstor(struct vcpu *v, uint64_t mask);
bool_t xsave_enabled(const struct vcpu *v);
-int __must_check validate_xstate(u64 xcr0, u64 xcr0_accum,
- const struct xsave_hdr *);
+int __must_check validate_xstate(const struct domain *d,
+ uint64_t xcr0, uint64_t xcr0_accum,
+ const struct xsave_hdr *hdr);
int __must_check handle_xsetbv(u32 index, u64 new_bv);
void expand_xsave_states(struct vcpu *v, void *dest, unsigned int size);
void compress_xsave_states(struct vcpu *v, const void *src, unsigned int size);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |