hv: vmcs: pass-through instruction INVPCID to VM

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 <binbin.wu@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Binbin Wu 2019-12-23 13:43:01 +08:00 committed by wenlingz
parent d330879ce5
commit 4ae350a091
1 changed files with 9 additions and 0 deletions

View File

@ -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_VAPIC | VMX_PROCBASED_CTLS2_EPT |VMX_PROCBASED_CTLS2_VPID |
VMX_PROCBASED_CTLS2_RDTSCP | VMX_PROCBASED_CTLS2_UNRESTRICT); 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()) { if (is_apicv_advanced_feature_supported()) {
value32 |= VMX_PROCBASED_CTLS2_VIRQ; value32 |= VMX_PROCBASED_CTLS2_VIRQ;
value32 |= VMX_PROCBASED_CTLS2_VAPIC_REGS; value32 |= VMX_PROCBASED_CTLS2_VAPIC_REGS;