diff mbox

[XTF,04/16] vvmx: add C wrappers of vmxon/vmread/vmptrld

Message ID 20161216134348.16236-5-haozhong.zhang@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Haozhong Zhang Dec. 16, 2016, 1:43 p.m. UTC
These C wrappers record the faults and VMfails in the execution of vmx
instructions vmxon, vmread and vmptrld. Further tests can use those
records to check if a VMX instruction is implemented correctly by Xen
in the nested VMX. Other VMX instructions will be added once their
test cases are added.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
 include/arch/x86/hvm/vmx/vmcs.h | 179 ++++++++++++++++++++++++++++++++++++++++
 tests/vvmx/Makefile             |   2 +-
 tests/vvmx/util.c               |  83 +++++++++++++++++++
 tests/vvmx/util.h               |  78 +++++++++++++++++
 tests/vvmx/vmxon.c              |   0
 5 files changed, 341 insertions(+), 1 deletion(-)
 create mode 100644 include/arch/x86/hvm/vmx/vmcs.h
 create mode 100644 tests/vvmx/util.c
 create mode 100644 tests/vvmx/util.h
 create mode 100644 tests/vvmx/vmxon.c

diff --git a/tests/vvmx/vmxon.c b/tests/vvmx/vmxon.c
new file mode 100644
index 0000000..e69de29

Comments

Andrew Cooper Dec. 16, 2016, 7:03 p.m. UTC | #1
On 16/12/16 13:43, Haozhong Zhang wrote:
> diff --git a/include/arch/x86/hvm/vmx/vmcs.h b/include/arch/x86/hvm/vmx/vmcs.h
> new file mode 100644
> index 0000000..e1a6ef8
> --- /dev/null
> +++ b/include/arch/x86/hvm/vmx/vmcs.h
> @@ -0,0 +1,179 @@
> +#ifndef XTF_X86_HVM_VMX_VMCS_H
> +#define XTF_X86_HVM_VMX_VMCS_H
> +
> +/* VMCS field encodings. */
> +#define VMCS_HIGH(x) ((x) | 1)
> +enum vmcs_field {
> +    VIRTUAL_PROCESSOR_ID            = 0x00000000,
> +    POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,
> +    EPTP_INDEX                      = 0x00000004,
> +#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES ... GS */

Unfortunately, there is probably a BSD/GPL licensing issue here.

XTF is BSD clause 2 licensed, because a lot of the core microkernel bits
are generally useful to other microkernel projects, and I have specific
plans to contribute improvements back to the likes of Mini-OS and
HVMLoader.  I would specifically like to maintain this property.

Xen, following its Linux heritage, is strictly GPLv2 (other than the
public headers, which are specifically different).


Having XTF use the same naming as Xen is convenient for development, and
I specifically don't want to get caught up in tricks like renaming
constants; these names inherit from the architecture manual and calling
them anything else would be even worse.  If we were to go down this
route, being able to keep the header file in sync would be useful, but
dual licensing it Xen would be complicated and confusing.

BSD and GPL are compatible licenses.  One option Ian suggested would be
to have a GPL subdirectory in XTF which clearly separates GPL content
from BSD content.  The resulting tests would become GPL, but the primary
distribution method is "git clone && make", so there are no issues
there.  I think it is reasonable to take this approach for header file
content like this, describing an external ABI, but I'd certainly like to
avoid doing anything similar for other content, as it complicates
contributing microkernel content back to other projects.

CC'ing various people for opinions.

~Andrew
Haozhong Zhang Dec. 19, 2016, 3:20 a.m. UTC | #2
On 12/16/16 19:03 +0000, Andrew Cooper wrote:
>On 16/12/16 13:43, Haozhong Zhang wrote:
>> diff --git a/include/arch/x86/hvm/vmx/vmcs.h b/include/arch/x86/hvm/vmx/vmcs.h
>> new file mode 100644
>> index 0000000..e1a6ef8
>> --- /dev/null
>> +++ b/include/arch/x86/hvm/vmx/vmcs.h
>> @@ -0,0 +1,179 @@
>> +#ifndef XTF_X86_HVM_VMX_VMCS_H
>> +#define XTF_X86_HVM_VMX_VMCS_H
>> +
>> +/* VMCS field encodings. */
>> +#define VMCS_HIGH(x) ((x) | 1)
>> +enum vmcs_field {
>> +    VIRTUAL_PROCESSOR_ID            = 0x00000000,
>> +    POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,
>> +    EPTP_INDEX                      = 0x00000004,
>> +#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES ... GS */
>
>Unfortunately, there is probably a BSD/GPL licensing issue here.
>
>XTF is BSD clause 2 licensed, because a lot of the core microkernel bits
>are generally useful to other microkernel projects, and I have specific
>plans to contribute improvements back to the likes of Mini-OS and
>HVMLoader.  I would specifically like to maintain this property.
>
>Xen, following its Linux heritage, is strictly GPLv2 (other than the
>public headers, which are specifically different).
>
>
>Having XTF use the same naming as Xen is convenient for development, and
>I specifically don't want to get caught up in tricks like renaming
>constants;

but renaming or taking names from other BSD-licensed projects [1] could
keep the whole project as purely BSD-licensed.

[1] https://github.com/freebsd/freebsd/blob/master/sys/amd64/vmm/intel/vmcs.h

> these names inherit from the architecture manual and calling
>them anything else would be even worse. If we were to go down this
>route, being able to keep the header file in sync would be useful, but
>dual licensing it Xen would be complicated and confusing.
>
>BSD and GPL are compatible licenses.  One option Ian suggested would be
>to have a GPL subdirectory in XTF which clearly separates GPL content
>from BSD content.  The resulting tests would become GPL, but the primary
>distribution method is "git clone && make", so there are no issues
>there.

If I want to use the BSD-licensed files individually in other
projects, will I need to keep a GPL license with them?

Thanks,
Haozhong

> I think it is reasonable to take this approach for header file
>content like this, describing an external ABI, but I'd certainly like to
>avoid doing anything similar for other content, as it complicates
>contributing microkernel content back to other projects.
>
>CC'ing various people for opinions.
>
>~Andrew
Lars Kurth Dec. 19, 2016, 2:41 p.m. UTC | #3
On 18/12/2016 21:20, "Haozhong Zhang" <haozhong.zhang@intel.com> wrote:

>On 12/16/16 19:03 +0000, Andrew Cooper wrote:

>>On 16/12/16 13:43, Haozhong Zhang wrote:

>>> diff --git a/include/arch/x86/hvm/vmx/vmcs.h

>>>b/include/arch/x86/hvm/vmx/vmcs.h

>>> new file mode 100644

>>> index 0000000..e1a6ef8

>>> --- /dev/null

>>> +++ b/include/arch/x86/hvm/vmx/vmcs.h

>>> @@ -0,0 +1,179 @@

>>> +#ifndef XTF_X86_HVM_VMX_VMCS_H

>>> +#define XTF_X86_HVM_VMX_VMCS_H

>>> +

>>> +/* VMCS field encodings. */

>>> +#define VMCS_HIGH(x) ((x) | 1)

>>> +enum vmcs_field {

>>> +    VIRTUAL_PROCESSOR_ID            = 0x00000000,

>>> +    POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,

>>> +    EPTP_INDEX                      = 0x00000004,

>>> +#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES

>>>... GS */

>>

>>Unfortunately, there is probably a BSD/GPL licensing issue here.

>>

>>XTF is BSD clause 2 licensed, because a lot of the core microkernel bits

>>are generally useful to other microkernel projects, and I have specific

>>plans to contribute improvements back to the likes of Mini-OS and

>>HVMLoader.  I would specifically like to maintain this property.

>>

>>Xen, following its Linux heritage, is strictly GPLv2 (other than the

>>public headers, which are specifically different).

>>

>>

>>Having XTF use the same naming as Xen is convenient for development, and

>>I specifically don't want to get caught up in tricks like renaming

>>constants;

>

>but renaming or taking names from other BSD-licensed projects [1] could

>keep the whole project as purely BSD-licensed.

>

>[1] 

>https://github.com/freebsd/freebsd/blob/master/sys/amd64/vmm/intel/vmcs.h


I am not sure what you mean.

>> these names inherit from the architecture manual and calling

>>them anything else would be even worse. If we were to go down this

>>route, being able to keep the header file in sync would be useful, but

>>dual licensing it Xen would be complicated and confusing.

>>

>>BSD and GPL are compatible licenses.  One option Ian suggested would be

>>to have a GPL subdirectory in XTF which clearly separates GPL content

>>from BSD content.  The resulting tests would become GPL, but the primary

>>distribution method is "git clone && make", so there are no issues

>>there.


This seems to be a workable approach.

Whether the test suite itself (when combined with minios or other non-GPL
baselines) are GPL or another license probably does not matter.
Separating the GPL code out, would be useful if the suite needed to be
combined with a baseline which is non-GPL compatible.

@Andy: you may want to have a chat with Ian and check whether the MPL 2.0
may be a better choice for XTF than BSD in this case. I have not looked
into how copyleft and MPL 2 work together though. Just a thought.

>If I want to use the BSD-licensed files individually in other

>projects, will I need to keep a GPL license with them?


I am assuming you mean whether the file needs a GPL (c) header? The answer
is no.
But the combined work will be GPL: for example let's say a folder A has
BSD files in it and a folder B has GPL files in it and you compile A and B
together to AB.exe, then AB.exe as a whole is licensed under the GPL.

>

>Thanks,

>Haozhong

>

>> I think it is reasonable to take this approach for header file

>>content like this, describing an external ABI, but I'd certainly like to

>>avoid doing anything similar for other content, as it complicates

>>contributing microkernel content back to other projects.

>>

>>CC'ing various people for opinions.

>>

>>~Andrew
Roger Pau Monne Dec. 19, 2016, 3:20 p.m. UTC | #4
On Fri, Dec 16, 2016 at 07:03:49PM +0000, Andrew Cooper wrote:
> On 16/12/16 13:43, Haozhong Zhang wrote:
> > diff --git a/include/arch/x86/hvm/vmx/vmcs.h b/include/arch/x86/hvm/vmx/vmcs.h
> > new file mode 100644
> > index 0000000..e1a6ef8
> > --- /dev/null
> > +++ b/include/arch/x86/hvm/vmx/vmcs.h
> > @@ -0,0 +1,179 @@
> > +#ifndef XTF_X86_HVM_VMX_VMCS_H
> > +#define XTF_X86_HVM_VMX_VMCS_H
> > +
> > +/* VMCS field encodings. */
> > +#define VMCS_HIGH(x) ((x) | 1)
> > +enum vmcs_field {
> > +    VIRTUAL_PROCESSOR_ID            = 0x00000000,
> > +    POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,
> > +    EPTP_INDEX                      = 0x00000004,
> > +#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES ... GS */
> 
> Unfortunately, there is probably a BSD/GPL licensing issue here.
> 
> XTF is BSD clause 2 licensed, because a lot of the core microkernel bits
> are generally useful to other microkernel projects, and I have specific
> plans to contribute improvements back to the likes of Mini-OS and
> HVMLoader.  I would specifically like to maintain this property.
> 
> Xen, following its Linux heritage, is strictly GPLv2 (other than the
> public headers, which are specifically different).

IANAL, but it seems quite weird to me that a set of defines or enums (without
any logic behind) can be put under a specific license, which seems to be the
case here. Certainly this is publicly available on the SDM, and it won't be
surprising for someone to code them in the exact same way AFAICT.

Roger.
Andrew Cooper Dec. 19, 2016, 3:24 p.m. UTC | #5
On 19/12/16 15:20, Roger Pau Monné wrote:
> On Fri, Dec 16, 2016 at 07:03:49PM +0000, Andrew Cooper wrote:
>> On 16/12/16 13:43, Haozhong Zhang wrote:
>>> diff --git a/include/arch/x86/hvm/vmx/vmcs.h b/include/arch/x86/hvm/vmx/vmcs.h
>>> new file mode 100644
>>> index 0000000..e1a6ef8
>>> --- /dev/null
>>> +++ b/include/arch/x86/hvm/vmx/vmcs.h
>>> @@ -0,0 +1,179 @@
>>> +#ifndef XTF_X86_HVM_VMX_VMCS_H
>>> +#define XTF_X86_HVM_VMX_VMCS_H
>>> +
>>> +/* VMCS field encodings. */
>>> +#define VMCS_HIGH(x) ((x) | 1)
>>> +enum vmcs_field {
>>> +    VIRTUAL_PROCESSOR_ID            = 0x00000000,
>>> +    POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,
>>> +    EPTP_INDEX                      = 0x00000004,
>>> +#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES ... GS */
>> Unfortunately, there is probably a BSD/GPL licensing issue here.
>>
>> XTF is BSD clause 2 licensed, because a lot of the core microkernel bits
>> are generally useful to other microkernel projects, and I have specific
>> plans to contribute improvements back to the likes of Mini-OS and
>> HVMLoader.  I would specifically like to maintain this property.
>>
>> Xen, following its Linux heritage, is strictly GPLv2 (other than the
>> public headers, which are specifically different).
> IANAL, but it seems quite weird to me that a set of defines or enums (without
> any logic behind) can be put under a specific license, which seems to be the
> case here. Certainly this is publicly available on the SDM, and it won't be
> surprising for someone to code them in the exact same way AFAICT.

Frankly, I was already on the fence with this, but Ian had a stronger
opinion.

If it were just the names, I wouldn't have raised an issue at all. 
After all, it is just a C implementation of an ABI described in the
Intel manual, and there are only a handful of ways to actually do that
and also end up something which compiles.

The extra comments and macros however, are more dubious.

~Andrew
Ian Jackson Dec. 19, 2016, 3:51 p.m. UTC | #6
Lars Kurth writes ("Re: [licensing] was: [XTF PATCH 04/16] vvmx: add C wrappers of vmxon/vmread/vmptrld"):
> @Andy: you may want to have a chat with Ian and check whether the MPL 2.0
> may be a better choice for XTF than BSD in this case. I have not looked
> into how copyleft and MPL 2 work together though. Just a thought.

They work badly together.  I would avoid the MPL for anything.
BSD2/MIT (ie a permissive licence) is correct for Andy's requirements.

Thanks,
Ian.
Andrew Cooper Dec. 19, 2016, 3:58 p.m. UTC | #7
On 19/12/16 03:20, Haozhong Zhang wrote:
> On 12/16/16 19:03 +0000, Andrew Cooper wrote:
>> On 16/12/16 13:43, Haozhong Zhang wrote:
>>> diff --git a/include/arch/x86/hvm/vmx/vmcs.h
>>> b/include/arch/x86/hvm/vmx/vmcs.h
>>> new file mode 100644
>>> index 0000000..e1a6ef8
>>> --- /dev/null
>>> +++ b/include/arch/x86/hvm/vmx/vmcs.h
>>> @@ -0,0 +1,179 @@
>>> +#ifndef XTF_X86_HVM_VMX_VMCS_H
>>> +#define XTF_X86_HVM_VMX_VMCS_H
>>> +
>>> +/* VMCS field encodings. */
>>> +#define VMCS_HIGH(x) ((x) | 1)
>>> +enum vmcs_field {
>>> +    VIRTUAL_PROCESSOR_ID            = 0x00000000,
>>> +    POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,
>>> +    EPTP_INDEX                      = 0x00000004,
>>> +#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /*
>>> ES ... GS */
>>
>> Unfortunately, there is probably a BSD/GPL licensing issue here.
>>
>> XTF is BSD clause 2 licensed, because a lot of the core microkernel bits
>> are generally useful to other microkernel projects, and I have specific
>> plans to contribute improvements back to the likes of Mini-OS and
>> HVMLoader.  I would specifically like to maintain this property.
>>
>> Xen, following its Linux heritage, is strictly GPLv2 (other than the
>> public headers, which are specifically different).
>>
>>
>> Having XTF use the same naming as Xen is convenient for development, and
>> I specifically don't want to get caught up in tricks like renaming
>> constants;
>
> but renaming or taking names from other BSD-licensed projects [1] could
> keep the whole project as purely BSD-licensed.

That would also work.

I also tend to only pull in defines which are actually used, but that is
just personal choice and to keep the size of the commits down.

>
> [1]
> https://github.com/freebsd/freebsd/blob/master/sys/amd64/vmm/intel/vmcs.h
>
>> these names inherit from the architecture manual and calling
>> them anything else would be even worse. If we were to go down this
>> route, being able to keep the header file in sync would be useful, but
>> dual licensing it Xen would be complicated and confusing.
>>
>> BSD and GPL are compatible licenses.  One option Ian suggested would be
>> to have a GPL subdirectory in XTF which clearly separates GPL content
>> from BSD content.  The resulting tests would become GPL, but the primary
>> distribution method is "git clone && make", so there are no issues
>> there.
>
> If I want to use the BSD-licensed files individually in other
> projects, will I need to keep a GPL license with them?

Only if the GPL file needed to be ported as well.  In this case, it is
only the VMX test which uses it, rather than any of the core code.

I don't plan on porting entire files to other projects, but individual
functions certainly.  (Having said that, I do plan on moving the entire
vsnprintf() implementation to hvmloader so it can actually format 64bit
integers).

~Andrew
diff mbox

Patch

diff --git a/include/arch/x86/hvm/vmx/vmcs.h b/include/arch/x86/hvm/vmx/vmcs.h
new file mode 100644
index 0000000..e1a6ef8
--- /dev/null
+++ b/include/arch/x86/hvm/vmx/vmcs.h
@@ -0,0 +1,179 @@ 
+#ifndef XTF_X86_HVM_VMX_VMCS_H
+#define XTF_X86_HVM_VMX_VMCS_H
+
+/* VMCS field encodings. */
+#define VMCS_HIGH(x) ((x) | 1)
+enum vmcs_field {
+    VIRTUAL_PROCESSOR_ID            = 0x00000000,
+    POSTED_INTR_NOTIFICATION_VECTOR = 0x00000002,
+    EPTP_INDEX                      = 0x00000004,
+#define GUEST_SEG_SELECTOR(sel) (GUEST_ES_SELECTOR + (sel) * 2) /* ES ... GS */
+    GUEST_ES_SELECTOR               = 0x00000800,
+    GUEST_CS_SELECTOR               = 0x00000802,
+    GUEST_SS_SELECTOR               = 0x00000804,
+    GUEST_DS_SELECTOR               = 0x00000806,
+    GUEST_FS_SELECTOR               = 0x00000808,
+    GUEST_GS_SELECTOR               = 0x0000080a,
+    GUEST_LDTR_SELECTOR             = 0x0000080c,
+    GUEST_TR_SELECTOR               = 0x0000080e,
+    GUEST_INTR_STATUS               = 0x00000810,
+    GUEST_PML_INDEX                 = 0x00000812,
+    HOST_ES_SELECTOR                = 0x00000c00,
+    HOST_CS_SELECTOR                = 0x00000c02,
+    HOST_SS_SELECTOR                = 0x00000c04,
+    HOST_DS_SELECTOR                = 0x00000c06,
+    HOST_FS_SELECTOR                = 0x00000c08,
+    HOST_GS_SELECTOR                = 0x00000c0a,
+    HOST_TR_SELECTOR                = 0x00000c0c,
+    IO_BITMAP_A                     = 0x00002000,
+    IO_BITMAP_B                     = 0x00002002,
+    MSR_BITMAP                      = 0x00002004,
+    VM_EXIT_MSR_STORE_ADDR          = 0x00002006,
+    VM_EXIT_MSR_LOAD_ADDR           = 0x00002008,
+    VM_ENTRY_MSR_LOAD_ADDR          = 0x0000200a,
+    PML_ADDRESS                     = 0x0000200e,
+    TSC_OFFSET                      = 0x00002010,
+    VIRTUAL_APIC_PAGE_ADDR          = 0x00002012,
+    APIC_ACCESS_ADDR                = 0x00002014,
+    PI_DESC_ADDR                    = 0x00002016,
+    VM_FUNCTION_CONTROL             = 0x00002018,
+    EPT_POINTER                     = 0x0000201a,
+    EOI_EXIT_BITMAP0                = 0x0000201c,
+#define EOI_EXIT_BITMAP(n) (EOI_EXIT_BITMAP0 + (n) * 2) /* n = 0...3 */
+    EPTP_LIST_ADDR                  = 0x00002024,
+    VMREAD_BITMAP                   = 0x00002026,
+    VMWRITE_BITMAP                  = 0x00002028,
+    VIRT_EXCEPTION_INFO             = 0x0000202a,
+    XSS_EXIT_BITMAP                 = 0x0000202c,
+    TSC_MULTIPLIER                  = 0x00002032,
+    GUEST_PHYSICAL_ADDRESS          = 0x00002400,
+    VMCS_LINK_POINTER               = 0x00002800,
+    GUEST_IA32_DEBUGCTL             = 0x00002802,
+    GUEST_PAT                       = 0x00002804,
+    GUEST_EFER                      = 0x00002806,
+    GUEST_PERF_GLOBAL_CTRL          = 0x00002808,
+    GUEST_PDPTE0                    = 0x0000280a,
+#define GUEST_PDPTE(n) (GUEST_PDPTE0 + (n) * 2) /* n = 0...3 */
+    GUEST_BNDCFGS                   = 0x00002812,
+    HOST_PAT                        = 0x00002c00,
+    HOST_EFER                       = 0x00002c02,
+    HOST_PERF_GLOBAL_CTRL           = 0x00002c04,
+    PIN_BASED_VM_EXEC_CONTROL       = 0x00004000,
+    CPU_BASED_VM_EXEC_CONTROL       = 0x00004002,
+    EXCEPTION_BITMAP                = 0x00004004,
+    PAGE_FAULT_ERROR_CODE_MASK      = 0x00004006,
+    PAGE_FAULT_ERROR_CODE_MATCH     = 0x00004008,
+    CR3_TARGET_COUNT                = 0x0000400a,
+    VM_EXIT_CONTROLS                = 0x0000400c,
+    VM_EXIT_MSR_STORE_COUNT         = 0x0000400e,
+    VM_EXIT_MSR_LOAD_COUNT          = 0x00004010,
+    VM_ENTRY_CONTROLS               = 0x00004012,
+    VM_ENTRY_MSR_LOAD_COUNT         = 0x00004014,
+    VM_ENTRY_INTR_INFO              = 0x00004016,
+    VM_ENTRY_EXCEPTION_ERROR_CODE   = 0x00004018,
+    VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
+    TPR_THRESHOLD                   = 0x0000401c,
+    SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
+    PLE_GAP                         = 0x00004020,
+    PLE_WINDOW                      = 0x00004022,
+    VM_INSTRUCTION_ERROR            = 0x00004400,
+    VM_EXIT_REASON                  = 0x00004402,
+    VM_EXIT_INTR_INFO               = 0x00004404,
+    VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
+    IDT_VECTORING_INFO              = 0x00004408,
+    IDT_VECTORING_ERROR_CODE        = 0x0000440a,
+    VM_EXIT_INSTRUCTION_LEN         = 0x0000440c,
+    VMX_INSTRUCTION_INFO            = 0x0000440e,
+#define GUEST_SEG_LIMIT(sel) (GUEST_ES_LIMIT + (sel) * 2) /* ES ... GS */
+    GUEST_ES_LIMIT                  = 0x00004800,
+    GUEST_CS_LIMIT                  = 0x00004802,
+    GUEST_SS_LIMIT                  = 0x00004804,
+    GUEST_DS_LIMIT                  = 0x00004806,
+    GUEST_FS_LIMIT                  = 0x00004808,
+    GUEST_GS_LIMIT                  = 0x0000480a,
+    GUEST_LDTR_LIMIT                = 0x0000480c,
+    GUEST_TR_LIMIT                  = 0x0000480e,
+    GUEST_GDTR_LIMIT                = 0x00004810,
+    GUEST_IDTR_LIMIT                = 0x00004812,
+#define GUEST_SEG_AR_BYTES(sel) (GUEST_ES_AR_BYTES + (sel) * 2) /* ES ... GS */
+    GUEST_ES_AR_BYTES               = 0x00004814,
+    GUEST_CS_AR_BYTES               = 0x00004816,
+    GUEST_SS_AR_BYTES               = 0x00004818,
+    GUEST_DS_AR_BYTES               = 0x0000481a,
+    GUEST_FS_AR_BYTES               = 0x0000481c,
+    GUEST_GS_AR_BYTES               = 0x0000481e,
+    GUEST_LDTR_AR_BYTES             = 0x00004820,
+    GUEST_TR_AR_BYTES               = 0x00004822,
+    GUEST_INTERRUPTIBILITY_INFO     = 0x00004824,
+    GUEST_ACTIVITY_STATE            = 0x00004826,
+    GUEST_SMBASE                    = 0x00004828,
+    GUEST_SYSENTER_CS               = 0x0000482a,
+    GUEST_PREEMPTION_TIMER          = 0x0000482e,
+    HOST_SYSENTER_CS                = 0x00004c00,
+    CR0_GUEST_HOST_MASK             = 0x00006000,
+    CR4_GUEST_HOST_MASK             = 0x00006002,
+    CR0_READ_SHADOW                 = 0x00006004,
+    CR4_READ_SHADOW                 = 0x00006006,
+    CR3_TARGET_VALUE0               = 0x00006008,
+#define CR3_TARGET_VALUE(n) (CR3_TARGET_VALUE0 + (n) * 2) /* n < CR3_TARGET_COUNT */
+    EXIT_QUALIFICATION              = 0x00006400,
+    GUEST_LINEAR_ADDRESS            = 0x0000640a,
+    GUEST_CR0                       = 0x00006800,
+    GUEST_CR3                       = 0x00006802,
+    GUEST_CR4                       = 0x00006804,
+#define GUEST_SEG_BASE(sel) (GUEST_ES_BASE + (sel) * 2) /* ES ... GS */
+    GUEST_ES_BASE                   = 0x00006806,
+    GUEST_CS_BASE                   = 0x00006808,
+    GUEST_SS_BASE                   = 0x0000680a,
+    GUEST_DS_BASE                   = 0x0000680c,
+    GUEST_FS_BASE                   = 0x0000680e,
+    GUEST_GS_BASE                   = 0x00006810,
+    GUEST_LDTR_BASE                 = 0x00006812,
+    GUEST_TR_BASE                   = 0x00006814,
+    GUEST_GDTR_BASE                 = 0x00006816,
+    GUEST_IDTR_BASE                 = 0x00006818,
+    GUEST_DR7                       = 0x0000681a,
+    GUEST_RSP                       = 0x0000681c,
+    GUEST_RIP                       = 0x0000681e,
+    GUEST_RFLAGS                    = 0x00006820,
+    GUEST_PENDING_DBG_EXCEPTIONS    = 0x00006822,
+    GUEST_SYSENTER_ESP              = 0x00006824,
+    GUEST_SYSENTER_EIP              = 0x00006826,
+    HOST_CR0                        = 0x00006c00,
+    HOST_CR3                        = 0x00006c02,
+    HOST_CR4                        = 0x00006c04,
+    HOST_FS_BASE                    = 0x00006c06,
+    HOST_GS_BASE                    = 0x00006c08,
+    HOST_TR_BASE                    = 0x00006c0a,
+    HOST_GDTR_BASE                  = 0x00006c0c,
+    HOST_IDTR_BASE                  = 0x00006c0e,
+    HOST_SYSENTER_ESP               = 0x00006c10,
+    HOST_SYSENTER_EIP               = 0x00006c12,
+    HOST_RSP                        = 0x00006c14,
+    HOST_RIP                        = 0x00006c16,
+};
+
+/* VM Instruction error numbers */
+enum vmx_insn_errno
+{
+    VMX_INSN_VMCLEAR_INVALID_PHYADDR       = 2,
+    VMX_INSN_VMLAUNCH_NONCLEAR_VMCS        = 4,
+    VMX_INSN_VMRESUME_NONLAUNCHED_VMCS     = 5,
+    VMX_INSN_INVALID_CONTROL_STATE         = 7,
+    VMX_INSN_INVALID_HOST_STATE            = 8,
+    VMX_INSN_VMPTRLD_INVALID_PHYADDR       = 9,
+    VMX_INSN_UNSUPPORTED_VMCS_COMPONENT    = 12,
+    VMX_INSN_VMXON_IN_VMX_ROOT             = 15,
+};
+
+#endif /* XTF_X86_HVM_VMX_VMCS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/vvmx/Makefile b/tests/vvmx/Makefile
index 54769fa..24d3720 100644
--- a/tests/vvmx/Makefile
+++ b/tests/vvmx/Makefile
@@ -6,6 +6,6 @@  TEST-ENVS := hvm64
 
 TEST-EXTRA-CFG := extra.cfg.in
 
-obj-perenv += main.o cpuid.o msr.o
+obj-perenv += main.o cpuid.o msr.o util.o
 
 include $(ROOT)/build/gen.mk
diff --git a/tests/vvmx/util.c b/tests/vvmx/util.c
new file mode 100644
index 0000000..8cd35c5
--- /dev/null
+++ b/tests/vvmx/util.c
@@ -0,0 +1,83 @@ 
+#include <xtf.h>
+#include <arch/x86/hvm/vmx/vmcs.h>
+#include "util.h"
+
+#define VMPTRLD_OPCODE  ".byte 0x0f,0xc7\n"             /* reg/opcode: /6 */
+#define VMREAD_OPCODE   ".byte 0x0f,0x78\n"
+#define VMXON_OPCODE    ".byte 0xf3,0x0f,0xc7\n"
+
+#define MODRM_EAX_06    ".byte 0x30\n" /* [EAX], with reg/opcode: /6 */
+#define MODRM_EAX_ECX   ".byte 0xc1\n" /* EAX, ECX */
+
+uint8_t vmxon(uint64_t paddr, exinfo_t *fault_info)
+{
+    exinfo_t fault = 0;
+    uint8_t valid = 0, invalid = 0;
+
+    asm volatile("1: "VMXON_OPCODE MODRM_EAX_06 "\n\t"
+                 "   setc %0; setz %1 \n\t"
+                 "2: \n\t"
+                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                 : "=q" (invalid), "=q" (valid), "+D" (fault)
+                 : "a" (&paddr)
+                 : "memory", "cc");
+
+    if ( fault && fault_info )
+        *fault_info = fault;
+
+    return (fault ? VMXERR_FAULT : 0) |
+           (valid ? VMXERR_VMFAIL_VALID : 0) |
+           (invalid ? VMXERR_VMFAIL_INVALID : 0);
+}
+
+uint8_t vmread(enum vmcs_field field, uint64_t *val, exinfo_t *fault_info)
+{
+    exinfo_t fault = 0;
+    uint8_t valid = 0, invalid = 0;
+
+    asm volatile("1: "VMREAD_OPCODE MODRM_EAX_ECX "\n\t"
+                 "   setc %0; setz %1 \n\t"
+                 "2: \n\t"
+                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                 : "=q" (invalid), "=q" (valid), "+D" (fault), "=c" (*val)
+                 : "a" (field)
+                 : "memory", "cc");
+
+    if ( fault && fault_info )
+        *fault_info = fault;
+
+    return (fault ? VMXERR_FAULT : 0) |
+           (valid ? VMXERR_VMFAIL_VALID : 0) |
+           (invalid ? VMXERR_VMFAIL_INVALID : 0);
+}
+
+uint8_t vmptrld(uint64_t paddr, exinfo_t *fault_info)
+{
+    exinfo_t fault = 0;
+    uint8_t valid = 0, invalid = 0;
+
+    asm volatile("1: "VMPTRLD_OPCODE MODRM_EAX_06 "\n\t"
+                 "   setc %0; setz %1 \n\t"
+                 "2: \n\t"
+                 _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                 : "=q" (invalid), "=q" (valid), "+D" (fault)
+                 : "a" (&paddr)
+                 : "memory", "cc");
+
+    if ( fault && fault_info )
+        *fault_info = fault;
+
+    return (fault ? VMXERR_FAULT : 0) |
+           (valid ? VMXERR_VMFAIL_VALID : 0) |
+           (invalid ? VMXERR_VMFAIL_INVALID : 0);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/vvmx/util.h b/tests/vvmx/util.h
new file mode 100644
index 0000000..57d3398
--- /dev/null
+++ b/tests/vvmx/util.h
@@ -0,0 +1,78 @@ 
+#ifndef XTF_TESTS_VVMX_UTIL_H
+#define XTF_TESTS_VVMX_UTIL_H
+
+#include <arch/x86/exinfo.h>
+#include <arch/x86/hvm/vmx/vmcs.h>
+
+/**
+ * Flags for errors during the execution of a VMX instruction.
+ *
+ * NB. Besides VMXERR_NOERR, other flags are not mutually exclusive,
+ * because we should not assume Xen implements the nested VMX
+ * instructions correctly.
+ */
+#define VMXERR_NOERR          0
+#define VMXERR_VMFAIL_VALID   (1 << 0)
+#define VMXERR_VMFAIL_INVALID (1 << 1)
+#define VMXERR_FAULT          (1 << 2)
+
+/**
+ * vmxon
+ *
+ * Parameters:
+ *  @paddr: the physical address of the VMXON region
+ *  @fault: return the information of fault encountered in the execution
+ *
+ * Return:
+ *  VMXERR_ flags.
+ *
+ *  If VMXERR_FAULT is present and @fault is not NULL, the fault
+ *  information will be returned via @fault.
+ */
+uint8_t vmxon(uint64_t paddr, exinfo_t *fault);
+
+/**
+ * vmread
+ *
+ * Parameters:
+ *  @field: the encoding of the VMCS field to read
+ *  @value: return the value of the VMCS field if no error is encountered
+ *  @fault: return the information of fault encountered in the execution
+ *
+ * Return:
+ *  VMXERR_ flags.
+ *
+ *  If VMXERR_FAULT is present and @fault is not NULL, the fault
+ *  information will be returned via @fault.
+ *
+ *  If VMXERR_NOERR is returned and @value is not NULL, the value of
+ *  VMCS field @field will be returned via @value.
+ */
+uint8_t vmread(enum vmcs_field field, uint64_t *value, exinfo_t *fault);
+
+/**
+ * vmptrld
+ *
+ * Parameters:
+ *  @paddr: the physical address of VMCS
+ *  @fault: return the information of fault encountered in the execution
+ *
+ * Return:
+ *  VMXERR_ flags.
+ *
+ *  If VMXERR_FAULT is present and @fault is not NULL, the fault
+ *  information will be returned via @fault.
+ */
+uint8_t vmptrld(uint64_t paddr, exinfo_t *fault);
+
+#endif /* XTF_TESTS_VVMX_UTIL_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */