All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: xen-devel <xen-devel@lists.xenproject.org>, Keir Fraser <keir@xen.org>
Subject: Re: [PATCH 3/3] x86/HVM: make hvm_efer_valid() honor guest features
Date: Fri, 9 Jan 2015 15:09:41 +0000	[thread overview]
Message-ID: <54AFEF35.5010002@citrix.com> (raw)
In-Reply-To: <54AFC7A502000078000531CD@mail.emea.novell.com>

On 09/01/15 11:20, Jan Beulich wrote:
>>>> On 08.01.15 at 19:49, <andrew.cooper3@citrix.com> wrote:
>> On 08/01/15 15:23, Jan Beulich wrote:
>>> Following the earlier similar change validating CR4 modifications.
>>>
>>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>>>
>>> --- a/xen/arch/x86/hvm/hvm.c
>>> +++ b/xen/arch/x86/hvm/hvm.c
>>> @@ -1672,20 +1672,53 @@ static int hvm_save_cpu_ctxt(struct doma
>>>      return 0;
>>>  }
>>>  
>>> -static bool_t hvm_efer_valid(struct domain *d,
>>> -                             uint64_t value, uint64_t efer_validbits)
>>> +static bool_t hvm_efer_valid(const struct vcpu *v, uint64_t value,
>>> +                             bool_t restore)
>>>  {
>>> -    if ( nestedhvm_enabled(d) && cpu_has_svm )
>>> -        efer_validbits |= EFER_SVME;
>>> +    unsigned int ext1_ecx = 0, ext1_edx = 0;
>>>  
>>> -    return !((value & ~efer_validbits) ||
>>> -             ((sizeof(long) != 8) && (value & EFER_LME)) ||
>>> -             (!cpu_has_svm && (value & EFER_SVME)) ||
>>> -             (!cpu_has_nx && (value & EFER_NX)) ||
>>> -             (!cpu_has_syscall && (value & EFER_SCE)) ||
>>> -             (!cpu_has_lmsl && (value & EFER_LMSLE)) ||
>>> -             (!cpu_has_ffxsr && (value & EFER_FFXSE)) ||
>>> -             ((value & (EFER_LME|EFER_LMA)) == EFER_LMA));
>>> +    if ( !restore && !is_hardware_domain(v->domain) )
>>> +    {
>>> +        unsigned int level;
>>> +
>>> +        ASSERT(v == current);
>>> +        hvm_cpuid(0x80000000, &level, NULL, NULL, NULL);
>>> +        if ( level >= 0x80000001 )
>>> +            hvm_cpuid(0x80000001, NULL, NULL, &ext1_ecx, &ext1_edx);
>>> +    }
>>> +    else
>>> +    {
>>> +        ext1_edx = boot_cpu_data.x86_capability[X86_FEATURE_LM / 32];
>>> +        ext1_ecx = boot_cpu_data.x86_capability[X86_FEATURE_SVM / 32];
>>> +    }
>>> +
>>> +    if ( (value & EFER_SCE) &&
>>> +         !(ext1_edx & cpufeat_mask(X86_FEATURE_SYSCALL)) )
>>> +        return 0;
>>> +
>>> +    if ( (value & (EFER_LME | EFER_LMA)) &&
>>> +         !(ext1_edx & cpufeat_mask(X86_FEATURE_LM)) )
>>> +        return 0;
>>> +
>>> +    if ( (value & EFER_LMA) && !(value & EFER_LME) )
>>> +        return 0;
>> The LME/LMA handling more complicated than this.
>>
>> LMA is read-only on Intel, but specified as read-write on AMD, with the
>> requirement that if it doesn't match the value generated by hardware, a
>> #GP fault will occur.  I believe this actually means it is read-only on
>> AMD as well.
>>
>> LMA only gets set by hardware after paging is enabled and the processor
>> switches properly into long mode, which means that there is a window
>> between setting LME and setting CR0.PG where LMA should read as 0.
> Did you note that hvm_set_efer() clears EFER_LMA before calling
> hvm_efer_valid(), thus avoiding all those issues?

I failed to appreciate its intent.

>
>> I think hvm_efer_valid() also needs the current EFER and CR0 to work out
>> what the current LMA should be, and reject any attempt to change it.
> I.e. this would be needed only for the restore path (and it not being
> done hasn't caused problems for me because guests don't normally
> get migrated before they fully enabled long mode).

Urgh.  In the restore case we don't have a current EFER to use.  In this
case I think it is acceptable to check that new_lma is (new_lme &&
!cr4.pg), which allows us to declare that the restore state is
consistent (presuming we have already validated cr4).

For the non-restore case, the caller takes care of removing LMA from
consideration.

>
>>> +    if ( (value & EFER_NX) && !(ext1_edx & cpufeat_mask(X86_FEATURE_NX)) )
>>> +        return 0;
>>> +
>>> +    if ( (value & EFER_SVME) &&
>>> +         (!(ext1_ecx & cpufeat_mask(X86_FEATURE_SVM)) ||
>>> +          !nestedhvm_enabled(v->domain)) )
>> This is going to cause an issue for the restore case, as the HVM PARAMs
>> follow the architectural state.
>>
>> I don't believe it is reasonable for nestedhvm_enabled() to disagree
>> with cpufeat_mask(X86_FEATURE_{SVM,VMX}), or for the toolstack to be
>> able to yank nestedhvm while the VM is active.
> I effectively only translated the pre-existing (and kind of suspicious
> to me) nestedhvm_enabled() use here.

So you did.  (My review focused a bit too much along the lines of "does
this new function match what the manuals state")

>
>> Looking at the checks when setting HVM_PARAM_NESTEDHVM, neither of the
>> guest feature flags are actually checked before setting up the nested
>> infrastructure.
> Which would be a separate issue.

It is indeed.  I apologize for rambling slightly - it was intended
purely as an observation.

>
>> Having said all of this, don't appear to be any migration records
>> associated with nested state (hardware-loaded VMCS/VMCB pointers,
>> currently nested?) which leads me to suspect that a domain actually
>> using nested virt is not going to survive a migration, so it might be
>> acceptable to fudge the checking of SVME for now.
> So am I getting you right that while these are all valid observations,
> you don't really ask for a change to the patch in this regard (i.e.
> taking care of above EFER_LMA issue is all that's needed, and even
> that only for the unusual case of a guest getting migrated in the
> middle of it enabling long mode on one of its CPUs)?

As the nested checks are the same as before, I am happy with them
staying as they are, and leaving work to whomever sees about fixing the
NESTEDHVM semantics.

~Andrew

  reply	other threads:[~2015-01-09 15:10 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-08 15:15 [PATCH 0/3] x86: XSA-111 follow-ups Jan Beulich
2015-01-08 15:22 ` [PATCH 1/3] x86: streamline hypercall_create_continuation() Jan Beulich
2015-01-08 16:01   ` Andrew Cooper
2015-01-08 16:11     ` Jan Beulich
2015-01-08 15:22 ` [PATCH 2/3] x86/HVM: clobber hypercall arguments just like for PV Jan Beulich
2015-01-08 17:20   ` Andrew Cooper
2015-01-08 15:23 ` [PATCH 3/3] x86/HVM: make hvm_efer_valid() honor guest features Jan Beulich
2015-01-08 15:56   ` Tim Deegan
2015-01-08 16:04     ` Jan Beulich
2015-01-08 18:57       ` Andrew Cooper
2015-01-08 18:49   ` Andrew Cooper
2015-01-09 11:20     ` Jan Beulich
2015-01-09 15:09       ` Andrew Cooper [this message]
2015-01-09 15:33         ` Jan Beulich
2015-01-09 15:36           ` Andrew Cooper
2015-01-08 15:53 ` [PATCH 0/3] x86: XSA-111 follow-ups Tim Deegan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54AFEF35.5010002@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=keir@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.