|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH XTF v2] Functional: Add a UMIP test
On Mon, Aug 14, 2017 at 11:35:47AM +0100, Andrew Cooper wrote:
> On 14/08/17 06:08, Boqun Feng (Intel) wrote:
> > Add a "umip" test for the User-Model Instruction Prevention. The test
> > simply tries to run sgdt/sidt/sldt/str/smsw in guest user-mode with
> > CR4_UMIP = 1.
> >
> > Signed-off-by: Boqun Feng (Intel) <boqun.feng@xxxxxxxxx>
>
> Thankyou for this. Its looking much better. Just a few comments.
>
Apologies for being so late, got interrupted by something more urgent..
> > ---
> > v1 --> v2:
> > * add a new write_cr4_safe()
> > * use %pe for exception print
> > * refactor the code based on Andrew's guide and advice
> >
> > Test results:
> >
> > * With UMIP patch:
> > ** boot with hvm_fep: SUCCESS
> > ** boot without hvm_fep: SKIP, due to "FEP support not detected.."
> >
> > * Without UMIP patch:
> > ** boot with hvm_fep: SKIP, due to "UMIP is not supported.."
> > ** boot without hvm_fep: SKIP, due to "UMIP is not supported.."
> >
> > * With UMIP cpuid exposed but CR4 invalid:
> > ** boot with hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.."
> > ** boot without hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.."
>
> What do you mean by CR4 invalid here?
>
I mean hvm_cr4_guest_valid_bits() doesn't return with X86_CR4_UMIP set,
and I manually modified my "Expose UMIP" patch to test this.
> > diff --git a/arch/x86/include/arch/lib.h b/arch/x86/include/arch/lib.h
> > index f608af9996f0..4f0d85290cf0 100644
> > --- a/arch/x86/include/arch/lib.h
> > +++ b/arch/x86/include/arch/lib.h
> > @@ -340,6 +340,19 @@ static inline void write_cr4(unsigned long cr4)
> > asm volatile ("mov %0, %%cr4" :: "r" (cr4));
> > }
> >
> > +static inline bool write_cr4_safe(unsigned long cr4)
> > +{
> > + exinfo_t fault = 0;
> > +
> > + asm volatile ("1: mov %1, %%cr4; 2:"
> > + _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
> > + : "+D" (fault)
> > + : "r" (cr4),
> > + "X" (ex_record_fault_edi));
> > +
> > + return !fault;
>
> To match the existing {rd,wr}msr_safe() implementation in XTF and the
> common usage in Linux and Xen, the return value should be 0 for success
> and nonzero for fault.
>
> i.e. you should "return fault;"
>
Got it.
> > diff --git a/tests/umip/main.c b/tests/umip/main.c
> > new file mode 100644
> > index 000000000000..fcaba4e34570
> > --- /dev/null
> > +++ b/tests/umip/main.c
> >
> > +
> > +static const struct stub {
> > + unsigned long (*fn)(unsigned long);
> > + const char *name;
> > +} stubs[] = {
> > + { stub_sgdt, "SGDT" },
> > + { stub_sidt, "SIDT" },
> > + { stub_sldt, "SLDT" },
> > + { stub_str, "STR" },
> > + { stub_smsw, "SMSW" },
> > +};
> > +
> > +void test_umip(bool umip_active, bool force)
>
> (For reasons explained below,) I'd rename this to test_insns(), and...
>
> > +{
> > + unsigned int i;
> > + bool user;
> > +
> > + for ( user = false; ; user = true )
> > + {
> > + exinfo_t exp = user && umip_active ? EXINFO_SYM(GP, 0) : 0;
> > +
> > + for ( i = 0; i < ARRAY_SIZE(stubs); i++)
> > + {
> > + const struct stub *s = &stubs[i];
> > + exinfo_t ret;
> > +
> > + ret = user ? exec_user_param(s->fn, force) : s->fn(force);
> > +
> > + /*
> > + * Tolerate the instruction emulator not understanding these
> > + * instructions in older releases of Xen.
> > + */
> > +
> > + if ( force && ret == EXINFO_SYM(UD, 0) )
> > + {
> > + static bool once;
> > +
> > + if ( !once )
> > + {
> > + xtf_skip("Skip: Emulator doesn't implement %s\n",
> > s->name);
> > + once = true;
> > + }
> > +
> > + continue;
> > + }
> > +
> > + if ( ret != exp )
> > + xtf_failure("Fail: %s %s\n"
> > + " expected %pe\n"
> > + " got %pe\n",
> > + user ? "user" : "supervisor", s->name,
> > + _p(exp), _p(ret));
> > + }
> > +
> > + if ( user )
> > + break;
> > + }
> > +}
>
> ... have this helper, which simplifies the test_main() logic.
>
> static void test_umip(bool umip_active)
> {
> test_insns(umip_active, false);
>
> if ( xtf_has_fep )
> test_insns(umip_active, true);
> }
>
Good point, will do this in V3.
> > +
> > +void test_main(void)
> > +{
> > + unsigned long cr4;
> > +
> > + /* run with UMIP inactive */
> > + test_umip(false, false);
> > +
> > + if ( !xtf_has_fep )
> > + xtf_skip("FEP support not detected - some tests will be
> > skipped\n");
>
> This text only needs to be shown once. I'd move it ahead of the first
> test_umip() call, and you can drop the else clauses given the new
> test_umip() implementation.
>
Agreed.
> > + else
> > + test_umip(false, true);
> > +
> > + if ( !cpu_has_umip )
> > + {
> > + xtf_skip("UMIP is not supported, skip the rest of test\n");
>
> Since I pointed you at the cpuid-faulting test case, I've had my code
> reviewed by someone in our testing team, and a logical issue was found.
> (As it turns out, when CPUID faulting is not available, writes
> attempting to enable it are squashed and appear to have succeeded. I'll
> fix that bug in due course.)
>
> At this point, we should check that attempting to set CR4.UMIP is
> prohibited.
>
Ok, I will add something like:
if ( !cpu_has_umip )
{
if (!write_cr4_safe(cr4 | X86_CR4_UMIP))
xtf_fail("UMIP unsupported, but setting CR4 bit succeeds");
else
xtf_skip("UMIP is not supported, skip the rest of test\n");
}
Thoughts?
Regards,
Boqun
> Otherwise, everything else looks fine.
>
> ~Andrew
Attachment:
signature.asc _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |