# HG changeset patch
# User Eddie Dong <eddie.dong@xxxxxxxxx>
# Date 1307003600 -28800
# Node ID 8264b01b476b1b695727f78d92ab0ce553aa7516
# Parent c8812151acfd6d9468f3407bc6a1a278cd764567
Define structure and access APIs for virtual VMCS.
Signed-off-by: Qing He <qing.he@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>
diff -r c8812151acfd -r 8264b01b476b xen/arch/x86/hvm/vmx/vvmx.c
--- a/xen/arch/x86/hvm/vmx/vvmx.c Thu Jun 02 16:33:20 2011 +0800
+++ b/xen/arch/x86/hvm/vmx/vvmx.c Thu Jun 02 16:33:20 2011 +0800
@@ -124,6 +124,84 @@ enum vmx_ops_result {
#define CASE_GET_REG(REG, reg) \
case VMX_REG_ ## REG: value = regs->reg; break
+static int vvmcs_offset(u32 width, u32 type, u32 index)
+{
+ int offset;
+
+ offset = (index & 0x1f) | type << 5 | width << 7;
+
+ if ( offset == 0 ) /* vpid */
+ offset = 0x3f;
+
+ return offset;
+}
+
+u64 __get_vvmcs(void *vvmcs, u32 vmcs_encoding)
+{
+ union vmcs_encoding enc;
+ u64 *content = (u64 *) vvmcs;
+ int offset;
+ u64 res;
+
+ enc.word = vmcs_encoding;
+ offset = vvmcs_offset(enc.width, enc.type, enc.index);
+ res = content[offset];
+
+ switch ( enc.width ) {
+ case VVMCS_WIDTH_16:
+ res &= 0xffff;
+ break;
+ case VVMCS_WIDTH_64:
+ if ( enc.access_type )
+ res >>= 32;
+ break;
+ case VVMCS_WIDTH_32:
+ res &= 0xffffffff;
+ break;
+ case VVMCS_WIDTH_NATURAL:
+ default:
+ break;
+ }
+
+ return res;
+}
+
+void __set_vvmcs(void *vvmcs, u32 vmcs_encoding, u64 val)
+{
+ union vmcs_encoding enc;
+ u64 *content = (u64 *) vvmcs;
+ int offset;
+ u64 res;
+
+ enc.word = vmcs_encoding;
+ offset = vvmcs_offset(enc.width, enc.type, enc.index);
+ res = content[offset];
+
+ switch ( enc.width ) {
+ case VVMCS_WIDTH_16:
+ res = val & 0xffff;
+ break;
+ case VVMCS_WIDTH_64:
+ if ( enc.access_type )
+ {
+ res &= 0xffffffff;
+ res |= val << 32;
+ }
+ else
+ res = val;
+ break;
+ case VVMCS_WIDTH_32:
+ res = val & 0xffffffff;
+ break;
+ case VVMCS_WIDTH_NATURAL:
+ default:
+ res = val;
+ break;
+ }
+
+ content[offset] = res;
+}
+
static unsigned long reg_read(struct cpu_user_regs *regs,
enum vmx_regs_enc index)
{
diff -r c8812151acfd -r 8264b01b476b xen/include/asm-x86/hvm/vmx/vvmx.h
--- a/xen/include/asm-x86/hvm/vmx/vvmx.h Thu Jun 02 16:33:20 2011 +0800
+++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Thu Jun 02 16:33:20 2011 +0800
@@ -96,5 +96,61 @@ uint32_t nvmx_vcpu_asid(struct vcpu *v);
int nvmx_handle_vmxon(struct cpu_user_regs *regs);
int nvmx_handle_vmxoff(struct cpu_user_regs *regs);
+/*
+ * Virtual VMCS layout
+ *
+ * Since physical VMCS layout is unknown, a custom layout is used
+ * for virtual VMCS seen by guest. It occupies a 4k page, and the
+ * field is offset by an 9-bit offset into u64[], The offset is as
+ * follow, which means every <width, type> pair has a max of 32
+ * fields available.
+ *
+ * 9 7 5 0
+ * --------------------------------
+ * offset: | width | type | index |
+ * --------------------------------
+ *
+ * Also, since the lower range <width=0, type={0,1}> has only one
+ * field: VPID, it is moved to a higher offset (63), and leaves the
+ * lower range to non-indexed field like VMCS revision.
+ *
+ */
+
+#define VVMCS_REVISION 0x40000001u
+
+struct vvmcs_header {
+ u32 revision;
+ u32 abort;
+};
+
+union vmcs_encoding {
+ struct {
+ u32 access_type : 1;
+ u32 index : 9;
+ u32 type : 2;
+ u32 rsv1 : 1;
+ u32 width : 2;
+ u32 rsv2 : 17;
+ };
+ u32 word;
+};
+
+enum vvmcs_encoding_width {
+ VVMCS_WIDTH_16 = 0,
+ VVMCS_WIDTH_64,
+ VVMCS_WIDTH_32,
+ VVMCS_WIDTH_NATURAL,
+};
+
+enum vvmcs_encoding_type {
+ VVMCS_TYPE_CONTROL = 0,
+ VVMCS_TYPE_RO,
+ VVMCS_TYPE_GSTATE,
+ VVMCS_TYPE_HSTATE,
+};
+
+u64 __get_vvmcs(void *vvmcs, u32 vmcs_encoding);
+void __set_vvmcs(void *vvmcs, u32 vmcs_encoding, u64 val);
+
#endif /* __ASM_X86_HVM_VVMX_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|