From: Gleb Natapov <gleb@redhat.com>
To: "Xu, Dongxiao" <dongxiao.xu@intel.com>
Cc: Orit Wasserman <owasserm@redhat.com>,
"kvm@vger.kernel.org" <kvm@vger.kernel.org>,
"mtosatti@redhat.com" <mtosatti@redhat.com>
Subject: Re: [PATCH 1/4] nested vmx: clean up for vmcs12 read and write
Date: Thu, 22 Nov 2012 08:45:15 +0200 [thread overview]
Message-ID: <20121122064515.GC21208@redhat.com> (raw)
In-Reply-To: <40776A41FC278F40B59438AD47D147A90FEA4D86@SHSMSX102.ccr.corp.intel.com>
On Thu, Nov 22, 2012 at 03:16:47AM +0000, Xu, Dongxiao wrote:
>
>
> > -----Original Message-----
> > From: Gleb Natapov [mailto:gleb@redhat.com]
> > Sent: Wednesday, November 21, 2012 9:27 PM
> > To: Xu, Dongxiao
> > Cc: kvm@vger.kernel.org; mtosatti@redhat.com
> > Subject: Re: [PATCH 1/4] nested vmx: clean up for vmcs12 read and write
> >
> > On Wed, Nov 21, 2012 at 05:04:34PM +0800, Dongxiao Xu wrote:
> > > abstract vmcs12_read and vmcs12_write functions to do the vmcs12
> > > read/write operations.
> > >
> > > Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
> > > ---
> > > arch/x86/kvm/vmx.c | 86
> > +++++++++++++++++++++++++++-------------------------
> > > 1 files changed, 45 insertions(+), 41 deletions(-)
> > >
> > > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index
> > > f858159..d8670e4 100644
> > > --- a/arch/x86/kvm/vmx.c
> > > +++ b/arch/x86/kvm/vmx.c
> > > @@ -5407,32 +5407,67 @@ static inline int vmcs_field_readonly(unsigned
> > long field)
> > > * some of the bits we return here (e.g., on 32-bit guests, only 32 bits of
> > > * 64-bit fields are to be returned).
> > > */
> > > -static inline bool vmcs12_read_any(struct kvm_vcpu *vcpu,
> > > - unsigned long field, u64 *ret)
> > > +static inline u64 vmcs12_read(struct kvm_vcpu *vcpu, unsigned long
> > > +field)
> > > {
> > > short offset = vmcs_field_to_offset(field);
> > > char *p;
> > >
> > > - if (offset < 0)
> > > + if (offset < 0) {
> > > + nested_vmx_failValid(vcpu,
> > VMXERR_UNSUPPORTED_VMCS_COMPONENT);
> > > + skip_emulated_instruction(vcpu);
> > > return 0;
> > > + }
> > >
> > > p = ((char *)(get_vmcs12(vcpu))) + offset;
> > >
> > > switch (vmcs_field_type(field)) {
> > > case VMCS_FIELD_TYPE_NATURAL_WIDTH:
> > > - *ret = *((natural_width *)p);
> > > + return *((natural_width *)p);
> > > + case VMCS_FIELD_TYPE_U16:
> > > + return *((u16 *)p);
> > > + case VMCS_FIELD_TYPE_U32:
> > > + return *((u32 *)p);
> > > + case VMCS_FIELD_TYPE_U64:
> > > + return *((u64 *)p);
> > > + default:
> > > + nested_vmx_failValid(vcpu,
> > VMXERR_UNSUPPORTED_VMCS_COMPONENT);
> > > + skip_emulated_instruction(vcpu);
> > > + return 0; /* can never happen. */
> > > + }
> > > +}
> > > +
> > > +static inline int vmcs12_write(struct kvm_vcpu *vcpu,
> > > + unsigned long field,
> > > + u64 value)
> > > +{
> > > + short offset = vmcs_field_to_offset(field);
> > > + char *p;
> > > +
> > > + if (offset < 0) {
> > > + nested_vmx_failValid(vcpu,
> > VMXERR_UNSUPPORTED_VMCS_COMPONENT);
> > > + skip_emulated_instruction(vcpu);
> > > + return 0;
> > > + }
> > > +
> > > + p = ((char *)(get_vmcs12(vcpu))) + offset;
> > > +
> > > + switch (vmcs_field_type(field)) {
> > > + case VMCS_FIELD_TYPE_NATURAL_WIDTH:
> > > + *(natural_width *)p = value;
> > > return 1;
> > > case VMCS_FIELD_TYPE_U16:
> > > - *ret = *((u16 *)p);
> > > + *(u16 *)p = value;
> > > return 1;
> > > case VMCS_FIELD_TYPE_U32:
> > > - *ret = *((u32 *)p);
> > > + *(u32 *)p = value;
> > > return 1;
> > > case VMCS_FIELD_TYPE_U64:
> > > - *ret = *((u64 *)p);
> > > + *(u64 *)p = value;
> > > return 1;
> > > default:
> > > - return 0; /* can never happen. */
> > > + nested_vmx_failValid(vcpu,
> > VMXERR_UNSUPPORTED_VMCS_COMPONENT);
> > > + skip_emulated_instruction(vcpu);
> > > + return 0;
> > > }
> > > }
> > >
> > > @@ -5466,11 +5501,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
> > > /* Decode instruction info and find the field to read */
> > > field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
> > > /* Read the field, zero-extended to a u64 field_value */
> > > - if (!vmcs12_read_any(vcpu, field, &field_value)) {
> > > - nested_vmx_failValid(vcpu,
> > VMXERR_UNSUPPORTED_VMCS_COMPONENT);
> > > - skip_emulated_instruction(vcpu);
> > > - return 1;
> > > - }
> > > + field_value = vmcs12_read(vcpu, field);
> > You do not handle failure here and always write back field_value even if
> > vmcs12_read() failed. Actually now it is impossible to detect a failure. Call to
> > nested_vmx_failValid() in vmcs12_read() will be overwritten by call to
> > nested_vmx_succeed() at the end of
> > handle_vmread() and skip_emulated_instruction() will be called twice.
>
> Thanks Gleb and Orit to raise this issue.
>
> What about moving the offset check outside the vmcs12_read() and vmcs12_write() function, and put it directly in handle_vmread() and handle_vmwrite()?
> I think we only need to do offset error check in handle_vmread() and handle_vmwrite() since they are to emulate correct behavior for guest VMM. For example, if guest VMM reads a field that is not valid or writes a field that is read only, then in emulation code handle_vmread() and handle_vmwrite, we need to raise error to guest VMM.
> For other calling of vmcs12_read() and vmcs12_write() functions in KVM hypervisor (see PATCH 3/4), actually the caller needs to ensure the field should be valid. Otherwise it is a bug in KVM hypervisor itself.
> Does it make sense? If so, I will revise this patch according to above.
>
Yes, it makes sense.
> Thanks,
> Dongxiao
>
> >
> > > + skip_emulated_instruction(vcpu);
> >
> > > /*
> > > * Now copy part of this value to register or memory, as requested.
> > > * Note that the number of bits actually copied is 32 or 64
> > > depending @@ -5500,8 +5531,6 @@ static int handle_vmwrite(struct
> > kvm_vcpu *vcpu)
> > > gva_t gva;
> > > unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
> > > u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
> > > - char *p;
> > > - short offset;
> > > /* The value to write might be 32 or 64 bits, depending on L1's long
> > > * mode, and eventually we need to write that into a field of several
> > > * possible lengths. The code below first zero-extends the value to
> > > 64 @@ -5537,33 +5566,8 @@ static int handle_vmwrite(struct kvm_vcpu
> > *vcpu)
> > > skip_emulated_instruction(vcpu);
> > > return 1;
> > > }
> > > -
> > > - offset = vmcs_field_to_offset(field);
> > > - if (offset < 0) {
> > > - nested_vmx_failValid(vcpu,
> > VMXERR_UNSUPPORTED_VMCS_COMPONENT);
> > > - skip_emulated_instruction(vcpu);
> > > - return 1;
> > > - }
> > > - p = ((char *) get_vmcs12(vcpu)) + offset;
> > > -
> > > - switch (vmcs_field_type(field)) {
> > > - case VMCS_FIELD_TYPE_U16:
> > > - *(u16 *)p = field_value;
> > > - break;
> > > - case VMCS_FIELD_TYPE_U32:
> > > - *(u32 *)p = field_value;
> > > - break;
> > > - case VMCS_FIELD_TYPE_U64:
> > > - *(u64 *)p = field_value;
> > > - break;
> > > - case VMCS_FIELD_TYPE_NATURAL_WIDTH:
> > > - *(natural_width *)p = field_value;
> > > - break;
> > > - default:
> > > - nested_vmx_failValid(vcpu,
> > VMXERR_UNSUPPORTED_VMCS_COMPONENT);
> > > - skip_emulated_instruction(vcpu);
> > > + if (!vmcs12_write(vcpu, field, field_value))
> > > return 1;
> > > - }
> > >
> > > nested_vmx_succeed(vcpu);
> > > skip_emulated_instruction(vcpu);
> > > --
> > > 1.7.1
> >
> > --
> > Gleb.
--
Gleb.
next prev parent reply other threads:[~2012-11-22 19:31 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-21 9:04 [PATCH 0/4] nested vmx code clean up and restructure Dongxiao Xu
2012-11-21 9:04 ` [PATCH 1/4] nested vmx: clean up for vmcs12 read and write Dongxiao Xu
2012-11-21 13:04 ` Gleb Natapov
2012-11-22 1:07 ` Xu, Dongxiao
2012-11-21 13:27 ` Gleb Natapov
2012-11-22 3:16 ` Xu, Dongxiao
2012-11-22 6:45 ` Gleb Natapov [this message]
2012-11-21 13:38 ` Orit Wasserman
2012-11-21 9:04 ` [PATCH 2/4] nested vmx: clean up for nested_cpu_has_xxx functions Dongxiao Xu
2012-11-21 9:04 ` [PATCH 3/4] nested vmx: use vmcs12_read/write() to operate VMCS fields Dongxiao Xu
2012-11-21 9:04 ` [PATCH 4/4] nested vmx: use a list to store the launched vmcs12 for L1 VMM Dongxiao Xu
2012-11-21 14:15 ` Gleb Natapov
2012-11-22 1:17 ` Xu, Dongxiao
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=20121122064515.GC21208@redhat.com \
--to=gleb@redhat.com \
--cc=dongxiao.xu@intel.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=owasserm@redhat.com \
/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.