Re: [PATCH 2/4] KVM: VMX: Add functions to fill VMCSINFO

2012-04-11 Thread Avi Kivity
On 04/11/2012 04:50 AM, zhangyanfei wrote:
 This patch is to implement the feature that at initialization of
 kvm_intel module, fills VMCSINFO with a VMCS revision identifier,
 and encoded offsets of VMCS fields. The reason why we put the
 VMCSINFO processing at the initialization of kvm_intel module
 is that it's dangerous to rob VMX resources while kvm module is
 loaded.

Maybe it should be done by a separate module.

 +
 + kvm_cpu_vmxon(__pa(per_cpu(vmxarea, raw_smp_processor_id(;
 + vmcs_load(vmcs);

Should do this after writing into the vmcs directly (vmcs_load() may
cache some information for vmcs_read()).

 +
 + VMCSINFO_REVISION_ID(vmcs-revision_id);
 +
 + /*
 +  * Write encoded offsets into VMCS data for later vmcs_read.
 +  */
 + for (offset = FIELD_START; offset  vmcs_config.size;
 +  offset += sizeof(u16))
 + *(u16 *)((char *)vmcs + offset) = ENCODING_OFFSET(offset);

This assumes vmcs field contents use the same encoding as
vmread/vmwrite.  I guess it's a reasonable assumption.


-- 
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/4] KVM: VMX: Add functions to fill VMCSINFO

2012-04-11 Thread zhangyanfei
于 2012年04月11日 16:48, Avi Kivity 写道:
 On 04/11/2012 04:50 AM, zhangyanfei wrote:
 This patch is to implement the feature that at initialization of
 kvm_intel module, fills VMCSINFO with a VMCS revision identifier,
 and encoded offsets of VMCS fields. The reason why we put the
 VMCSINFO processing at the initialization of kvm_intel module
 is that it's dangerous to rob VMX resources while kvm module is
 loaded.
 
 Maybe it should be done by a separate module.
 

If we put vmcsinfo processing at the initialization of kvm_intel module,
as soon as the kvm_intel module is loaded, VMCSINFO is filled. And it is
because vmcsinfo processing is at the initialization of kvm_intel module,
no kvm guests are running, so it will not rob any VMX resources.

If it is done by a separate module, I am afraid this module may not be
loaded when the kernel needs VMCSINFO.

 +
 +kvm_cpu_vmxon(__pa(per_cpu(vmxarea, raw_smp_processor_id(;
 +vmcs_load(vmcs);
 
 Should do this after writing into the vmcs directly (vmcs_load() may
 cache some information for vmcs_read()).


Hmm, thanks for pointing this.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/4] KVM: VMX: Add functions to fill VMCSINFO

2012-04-11 Thread Avi Kivity
On 04/11/2012 01:34 PM, zhangyanfei wrote:
 于 2012年04月11日 16:48, Avi Kivity 写道:
  On 04/11/2012 04:50 AM, zhangyanfei wrote:
  This patch is to implement the feature that at initialization of
  kvm_intel module, fills VMCSINFO with a VMCS revision identifier,
  and encoded offsets of VMCS fields. The reason why we put the
  VMCSINFO processing at the initialization of kvm_intel module
  is that it's dangerous to rob VMX resources while kvm module is
  loaded.
  
  Maybe it should be done by a separate module.
  

 If we put vmcsinfo processing at the initialization of kvm_intel module,
 as soon as the kvm_intel module is loaded, VMCSINFO is filled. And it is
 because vmcsinfo processing is at the initialization of kvm_intel module,
 no kvm guests are running, so it will not rob any VMX resources.

 If it is done by a separate module, I am afraid this module may not be
 loaded when the kernel needs VMCSINFO.


You can make the module autoload when the vmx cpufeature is detected. 
But then there is an ordering problem wrt kvm-intel.

-- 
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/4] KVM: VMX: Add functions to fill VMCSINFO

2012-04-10 Thread zhangyanfei
This patch is to implement the feature that at initialization of
kvm_intel module, fills VMCSINFO with a VMCS revision identifier,
and encoded offsets of VMCS fields. The reason why we put the
VMCSINFO processing at the initialization of kvm_intel module
is that it's dangerous to rob VMX resources while kvm module is
loaded.

Note, offsets of fields below will not be filled into VMCSINFO:
1. fields defined in Intel specification (Intel® 64 and
   IA-32 Architectures Software Developer’s Manual, Volume
   3C) but not defined in *vmcs_field*.
2. fields don't exist because their corresponding control bits
   are not set.

Signed-off-by: zhangyanfei zhangyan...@cn.fujitsu.com
---
 arch/x86/kvm/vmx.c |  350 
 1 files changed, 350 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index ad85adf..e98fafa 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -41,6 +41,7 @@
 #include asm/i387.h
 #include asm/xcr.h
 #include asm/perf_event.h
+#include asm/vmcsinfo.h
 
 #include trace.h
 
@@ -2599,6 +2600,353 @@ static __init int alloc_kvm_area(void)
return 0;
 }
 
+/*
+ * For caculating offsets of fields in VMCS data, we index every 16-bit
+ * field by this kind of format:
+ * | - 16 bits -- |
+ * +-+-++-+
+ * | high 7 bits |1| low 7 bits |0|
+ * +-+-++-+
+ * In high byte, the lowest bit must be 1; In low byte, the lowest bit
+ * must be 0. The two bits are set like this in case indexes in VMCS
+ * data are read as big endian mode.
+ * The remaining 14 bits of the index indicate the real offset of the
+ * field. Because the size of a VMCS region is at most 4 KBytes, so
+ * 14 bits are enough to index the whole VMCS region.
+ *
+ * ENCODING_OFFSET: encode the offset into the index of this kind.
+ */
+#define OFFSET_HIGH_SHIFT (7)
+#define OFFSET_LOW_MASK   ((1  OFFSET_HIGH_SHIFT) - 1) /* 0x7f */
+#define OFFSET_HIGH_MASK  (OFFSET_LOW_MASK  OFFSET_HIGH_SHIFT) /* 0x3f80 */
+#define ENCODING_OFFSET(offset) \
+   offset)  OFFSET_LOW_MASK)  1) + \
+   offset)  OFFSET_HIGH_MASK)  2) | 0x100))
+
+/*
+ * We separate these five control fields from other fields
+ * because some fields only exist on processors that support
+ * the 1-setting of control bits in the five control fields.
+ */
+static inline void append_control_field(void)
+{
+#define CONTROL_FIELD_OFFSET(field) \
+   VMCSINFO_FIELD32(field, vmcs_read32(field))
+
+   CONTROL_FIELD_OFFSET(PIN_BASED_VM_EXEC_CONTROL);
+   CONTROL_FIELD_OFFSET(CPU_BASED_VM_EXEC_CONTROL);
+   if (cpu_has_secondary_exec_ctrls()) {
+   CONTROL_FIELD_OFFSET(SECONDARY_VM_EXEC_CONTROL);
+   }
+   CONTROL_FIELD_OFFSET(VM_EXIT_CONTROLS);
+   CONTROL_FIELD_OFFSET(VM_ENTRY_CONTROLS);
+}
+
+static inline void append_field16(void)
+{
+#define FIELD_OFFSET16(field) \
+   VMCSINFO_FIELD16(field, vmcs_read16(field));
+
+   FIELD_OFFSET16(GUEST_ES_SELECTOR);
+   FIELD_OFFSET16(GUEST_CS_SELECTOR);
+   FIELD_OFFSET16(GUEST_SS_SELECTOR);
+   FIELD_OFFSET16(GUEST_DS_SELECTOR);
+   FIELD_OFFSET16(GUEST_FS_SELECTOR);
+   FIELD_OFFSET16(GUEST_GS_SELECTOR);
+   FIELD_OFFSET16(GUEST_LDTR_SELECTOR);
+   FIELD_OFFSET16(GUEST_TR_SELECTOR);
+   FIELD_OFFSET16(HOST_ES_SELECTOR);
+   FIELD_OFFSET16(HOST_CS_SELECTOR);
+   FIELD_OFFSET16(HOST_SS_SELECTOR);
+   FIELD_OFFSET16(HOST_DS_SELECTOR);
+   FIELD_OFFSET16(HOST_FS_SELECTOR);
+   FIELD_OFFSET16(HOST_GS_SELECTOR);
+   FIELD_OFFSET16(HOST_TR_SELECTOR);
+}
+
+static inline void append_field64(void)
+{
+#define FIELD_OFFSET64(field) \
+   VMCSINFO_FIELD64(field, vmcs_read64(field));
+
+   FIELD_OFFSET64(IO_BITMAP_A);
+   FIELD_OFFSET64(IO_BITMAP_A_HIGH);
+   FIELD_OFFSET64(IO_BITMAP_B);
+   FIELD_OFFSET64(IO_BITMAP_B_HIGH);
+   FIELD_OFFSET64(VM_EXIT_MSR_STORE_ADDR);
+   FIELD_OFFSET64(VM_EXIT_MSR_STORE_ADDR_HIGH);
+   FIELD_OFFSET64(VM_EXIT_MSR_LOAD_ADDR);
+   FIELD_OFFSET64(VM_EXIT_MSR_LOAD_ADDR_HIGH);
+   FIELD_OFFSET64(VM_ENTRY_MSR_LOAD_ADDR);
+   FIELD_OFFSET64(VM_ENTRY_MSR_LOAD_ADDR_HIGH);
+   FIELD_OFFSET64(TSC_OFFSET);
+   FIELD_OFFSET64(TSC_OFFSET_HIGH);
+   FIELD_OFFSET64(VMCS_LINK_POINTER);
+   FIELD_OFFSET64(VMCS_LINK_POINTER_HIGH);
+   FIELD_OFFSET64(GUEST_IA32_DEBUGCTL);
+   FIELD_OFFSET64(GUEST_IA32_DEBUGCTL_HIGH);
+
+   if (cpu_has_vmx_msr_bitmap()) {
+   FIELD_OFFSET64(MSR_BITMAP);
+   FIELD_OFFSET64(MSR_BITMAP_HIGH);
+   }
+
+   if (cpu_has_vmx_tpr_shadow()) {
+   FIELD_OFFSET64(VIRTUAL_APIC_PAGE_ADDR);
+   FIELD_OFFSET64(VIRTUAL_APIC_PAGE_ADDR_HIGH);
+   }
+
+   if (cpu_has_secondary_exec_ctrls()) {
+   if (vmcs_config.cpu_based_2nd_exec_ctrl 
+