131 lines
4.5 KiB
Diff
131 lines
4.5 KiB
Diff
|
References: FATE#313605
|
||
|
|
||
|
# HG changeset patch
|
||
|
# User Jiongxi Li <jiongxi.li@intel.com>
|
||
|
# Date 1347912248 -3600
|
||
|
# Node ID ec60de627945f17ec2ce5c14e1224b59403875f7
|
||
|
# Parent 62de66cec48a1716bb700912da451a26296b8d1e
|
||
|
xen: enable APIC-Register Virtualization
|
||
|
|
||
|
Add APIC register virtualization support
|
||
|
- APIC read doesn't cause VM-Exit
|
||
|
- APIC write becomes trap-like
|
||
|
|
||
|
Signed-off-by: Gang Wei <gang.wei@intel.com>
|
||
|
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
|
||
|
Signed-off-by: Jiongxi Li <jiongxi.li@intel.com>
|
||
|
|
||
|
--- a/xen/arch/x86/hvm/vlapic.c
|
||
|
+++ b/xen/arch/x86/hvm/vlapic.c
|
||
|
@@ -823,6 +823,14 @@ static int vlapic_write(struct vcpu *v,
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
+int vlapic_apicv_write(struct vcpu *v, unsigned int offset)
|
||
|
+{
|
||
|
+ uint32_t val = vlapic_get_reg(vcpu_vlapic(v), offset);
|
||
|
+
|
||
|
+ vlapic_reg_write(v, offset, val);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
int hvm_x2apic_msr_write(struct vcpu *v, unsigned int msr, uint64_t msr_content)
|
||
|
{
|
||
|
struct vlapic *vlapic = vcpu_vlapic(v);
|
||
|
--- a/xen/arch/x86/hvm/vmx/vmcs.c
|
||
|
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
|
||
|
@@ -89,6 +89,7 @@ static void __init vmx_display_features(
|
||
|
P(cpu_has_vmx_vnmi, "Virtual NMI");
|
||
|
P(cpu_has_vmx_msr_bitmap, "MSR direct-access bitmap");
|
||
|
P(cpu_has_vmx_unrestricted_guest, "Unrestricted Guest");
|
||
|
+ P(cpu_has_vmx_apic_reg_virt, "APIC Register Virtualization");
|
||
|
#undef P
|
||
|
|
||
|
if ( !printed )
|
||
|
@@ -186,6 +187,14 @@ static int vmx_init_vmcs_config(void)
|
||
|
if ( opt_unrestricted_guest_enabled )
|
||
|
opt |= SECONDARY_EXEC_UNRESTRICTED_GUEST;
|
||
|
|
||
|
+ /*
|
||
|
+ * "APIC Register Virtualization"
|
||
|
+ * can be set only when "use TPR shadow" is set
|
||
|
+ */
|
||
|
+ if ( _vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW )
|
||
|
+ opt |= SECONDARY_EXEC_APIC_REGISTER_VIRT;
|
||
|
+
|
||
|
+
|
||
|
_vmx_secondary_exec_control = adjust_vmx_controls(
|
||
|
"Secondary Exec Control", min, opt,
|
||
|
MSR_IA32_VMX_PROCBASED_CTLS2, &mismatch);
|
||
|
--- a/xen/arch/x86/hvm/vmx/vmx.c
|
||
|
+++ b/xen/arch/x86/hvm/vmx/vmx.c
|
||
|
@@ -2274,6 +2274,16 @@ static void vmx_idtv_reinject(unsigned l
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+static int vmx_handle_apic_write(void)
|
||
|
+{
|
||
|
+ unsigned long exit_qualification = __vmread(EXIT_QUALIFICATION);
|
||
|
+ unsigned int offset = exit_qualification & 0xfff;
|
||
|
+
|
||
|
+ ASSERT(cpu_has_vmx_apic_reg_virt);
|
||
|
+
|
||
|
+ return vlapic_apicv_write(current, offset);
|
||
|
+}
|
||
|
+
|
||
|
void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||
|
{
|
||
|
unsigned int exit_reason, idtv_info, intr_info = 0, vector = 0;
|
||
|
@@ -2729,6 +2739,11 @@ void vmx_vmexit_handler(struct cpu_user_
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
+ case EXIT_REASON_APIC_WRITE:
|
||
|
+ if ( vmx_handle_apic_write() )
|
||
|
+ hvm_inject_hw_exception(TRAP_gp_fault, 0);
|
||
|
+ break;
|
||
|
+
|
||
|
case EXIT_REASON_ACCESS_GDTR_OR_IDTR:
|
||
|
case EXIT_REASON_ACCESS_LDTR_OR_TR:
|
||
|
case EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED:
|
||
|
--- a/xen/include/asm-x86/hvm/vlapic.h
|
||
|
+++ b/xen/include/asm-x86/hvm/vlapic.h
|
||
|
@@ -103,6 +103,8 @@ void vlapic_EOI_set(struct vlapic *vlapi
|
||
|
|
||
|
int vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
|
||
|
|
||
|
+int vlapic_apicv_write(struct vcpu *v, unsigned int offset);
|
||
|
+
|
||
|
struct vlapic *vlapic_lowest_prio(
|
||
|
struct domain *d, struct vlapic *source,
|
||
|
int short_hand, uint8_t dest, uint8_t dest_mode);
|
||
|
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||
|
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
|
||
|
@@ -182,6 +182,7 @@ extern u32 vmx_vmentry_control;
|
||
|
#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
|
||
|
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
|
||
|
#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
|
||
|
+#define SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100
|
||
|
#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
|
||
|
#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
|
||
|
extern u32 vmx_secondary_exec_control;
|
||
|
@@ -230,6 +231,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr
|
||
|
SECONDARY_EXEC_UNRESTRICTED_GUEST)
|
||
|
#define cpu_has_vmx_ple \
|
||
|
(vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
|
||
|
+#define cpu_has_vmx_apic_reg_virt \
|
||
|
+ (vmx_secondary_exec_control & SECONDARY_EXEC_APIC_REGISTER_VIRT)
|
||
|
|
||
|
/* GUEST_INTERRUPTIBILITY_INFO flags. */
|
||
|
#define VMX_INTR_SHADOW_STI 0x00000001
|
||
|
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
|
||
|
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
|
||
|
@@ -129,6 +129,7 @@ void vmx_update_cpu_exec_control(struct
|
||
|
#define EXIT_REASON_INVVPID 53
|
||
|
#define EXIT_REASON_WBINVD 54
|
||
|
#define EXIT_REASON_XSETBV 55
|
||
|
+#define EXIT_REASON_APIC_WRITE 56
|
||
|
#define EXIT_REASON_INVPCID 58
|
||
|
|
||
|
/*
|