From 4ae350a091ac973e70ee3d0791bbedaab4b7fec0 Mon Sep 17 00:00:00 2001 From: Binbin Wu Date: Mon, 23 Dec 2019 13:43:01 +0800 Subject: [PATCH] hv: vmcs: pass-through instruction INVPCID to VM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to SDM Vol.3 Section 25.3, behavior of the INVPCID instruction is determined first by the setting of the “enable INVPCID” VM-execution control: - If the “enable INVPCID” VM-execution control is 0, INVPCID causes an invalid-opcode exception (#UD). - If the “enable INVPCID” VM-execution control is 1, treatment is based on the setting of the “INVLPG exiting” VM-execution control: * If the “INVLPG exiting” VM-execution control is 0, INVPCID operates normally. * If the “INVLPG exiting” VM-execution control is 1, INVPCID causes a VM exit. In current implementation, hypervisor doesn't set “INVLPG exiting” VM-execution control, this patch sets “enable INVPCID” VM-execution control to 1 when the instruction is supported by physical cpu. If INVPCID is supported by physical cpu, INVPCID will not cause VM exit in VM. If INVPCID is not supported by physical cpu, INVPCID causes an #UD in VM. When INVPCID is passed-through to VM, According to SDM Vol.3 28.3.3.1, INVPCID instruction invalidates linear mappings and combined mappings. They are required to do so only for the current VPID. HV assigned a unique vpid for each vCPU, if guest uses wrong PCID, it would not affect other vCPUs. Tracked-On: #4296 Signed-off-by: Binbin Wu Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vmcs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hypervisor/arch/x86/guest/vmcs.c b/hypervisor/arch/x86/guest/vmcs.c index d1f2c14cf..e0b7a46aa 100644 --- a/hypervisor/arch/x86/guest/vmcs.c +++ b/hypervisor/arch/x86/guest/vmcs.c @@ -299,6 +299,15 @@ static void init_exec_ctrl(struct acrn_vcpu *vcpu) VMX_PROCBASED_CTLS2_VAPIC | VMX_PROCBASED_CTLS2_EPT |VMX_PROCBASED_CTLS2_VPID | VMX_PROCBASED_CTLS2_RDTSCP | VMX_PROCBASED_CTLS2_UNRESTRICT); + /* SDM Vol3, 25.3, setting "enable INVPCID" VM-execution to 1 with "INVLPG exiting" disabled, + * passes-through INVPCID instruction to guest if the instruction is supported. + */ + if (pcpu_has_cap(X86_FEATURE_INVPCID)) { + value32 |= VMX_PROCBASED_CTLS2_INVPCID; + } else { + value32 &= ~VMX_PROCBASED_CTLS2_INVPCID; + } + if (is_apicv_advanced_feature_supported()) { value32 |= VMX_PROCBASED_CTLS2_VIRQ; value32 |= VMX_PROCBASED_CTLS2_VAPIC_REGS;