|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/3 v2] x86emul: conditionally clear BNDn for branches
On 12/12/16 10:00, Jan Beulich wrote:
> @@ -1791,6 +1795,34 @@ static int inject_swint(enum x86_swint_t
> generate_exception(fault_type, error_code);
> }
>
> +static void clear_bnd(struct x86_emulate_ctxt *ctxt,
> + const struct x86_emulate_ops *ops, enum vex_pfx pfx)
As with register_address_adjust(), this would be better as adjust_bnd()
as we don't necessarily clear them.
> +{
> + uint64_t bndcfg;
> + int rc;
> +
> + if ( pfx == vex_f2 || !vcpu_has_mpx() )
This is an awkward edgecase of the rules concerning the host_ variants,
but we will take a fault from xsave/xrstor for using XSTATE_BND* if the
host doesn't support MPX.
> + return;
> +
> + if ( !mode_ring0() )
> + bndcfg = read_bndcfgu();
> + else if ( !ops->read_msr ||
> + ops->read_msr(MSR_BNDCFGS, &bndcfg, ctxt) != X86EMUL_OKAY )
> + return;
> + if ( (bndcfg & BNDCFG_ENABLE) && !(bndcfg & BNDCFG_PRESERVE) )
> + {
> + /*
> + * Using BNDMK or any other MPX instruction here is pointless, as
> + * we run with MPX disabled ourselves, and hence they're all no-ops.
> + * Therefore we have two ways to clear BNDn: Enable MPX temporarily
> + * (in which case executing any suitable non-prefixed branch
> + * instruction would do), or use XRSTOR.
> + */
> + xstate_set_init(XSTATE_BNDREGS);
> + }
> + done:;
> +}
> +
> int x86emul_unhandleable_rw(
> enum x86_segment seg,
> unsigned long offset,
> --- a/xen/arch/x86/xstate.c
> +++ b/xen/arch/x86/xstate.c
> @@ -723,6 +741,66 @@ int handle_xsetbv(u32 index, u64 new_bv)
> return 0;
> }
>
> +uint64_t read_bndcfgu(void)
> +{
> + unsigned long cr0 = read_cr0();
> + struct xsave_struct *xstate
> + = idle_vcpu[smp_processor_id()]->arch.xsave_area;
> + const struct xstate_bndcsr *bndcsr;
> +
> + ASSERT(cpu_has_mpx);
> + clts();
> +
> + if ( cpu_has_xsavec )
> + {
> + asm ( ".byte 0x0f,0xc7,0x27\n" /* xsavec */
> + : "=m" (*xstate)
> + : "a" (XSTATE_BNDCSR), "d" (0), "D" (xstate) );
> +
> + bndcsr = (void *)(xstate + 1);
> + }
> + else
> + {
> + alternative_io(".byte 0x0f,0xae,0x27\n", /* xsave */
> + ".byte 0x0f,0xae,0x37\n", /* xsaveopt */
> + X86_FEATURE_XSAVEOPT,
> + "=m" (*xstate),
> + "a" (XSTATE_BNDCSR), "d" (0), "D" (xstate));
I am not certain this is safe. xsaveopt has an extra optimisation to do
with whether the state has been internally modified. Because we use an
xsave area from the idle vcpu, I can't see anything which prevents the
LAXA (linear address of XSAVE area) optimisation kicking in, causing us
to observe a zero in xstate_bv despite BNDCSR having a non-zero value
loaded in hardware.
> +
> + bndcsr = (void *)xstate + xstate_offsets[_XSTATE_BNDCSR];
> + }
> +
> + if ( cr0 & X86_CR0_TS )
> + write_cr0(cr0);
> +
> + return xstate->xsave_hdr.xstate_bv & XSTATE_BNDCSR ? bndcsr->bndcfgu : 0;
> +}
> +
> +void xstate_set_init(uint64_t mask)
> +{
> + unsigned long cr0 = read_cr0();
> + unsigned long xcr0 = this_cpu(xcr0);
> + struct vcpu *v = idle_vcpu[smp_processor_id()];
> + struct xsave_struct *xstate = v->arch.xsave_area;
> +
> + if ( ~xfeature_mask & mask )
> + return;
As the function is void, this should be an ASSERT or BUG. IMO, it is a
caller error to ask for a feature to be reset for hardware which doesn't
support the requested state.
> +
> + if ( (~xcr0 & mask) && !set_xcr0(xcr0 | mask) )
> + return;
> +
> + clts();
> +
> + memset(&xstate->xsave_hdr, 0, sizeof(xstate->xsave_hdr));
> + xrstor(v, mask);
> +
> + if ( cr0 & X86_CR0_TS )
> + write_cr0(cr0);
> +
> + if ( ~xcr0 & mask )
> + xsetbv(XCR_XFEATURE_ENABLED_MASK, xcr0);
Shouldn't this be set_xcr0() again, to undo the possible clobbering of
this_cpu(xcr0) ?
~Andrew
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |