Commit cea54838 authored by Jim Mattson's avatar Jim Mattson Committed by Juerg Haefliger

kvm: nVMX: VMCLEAR an active shadow VMCS after last use

BugLink: https://bugs.launchpad.net/bugs/1811646

After a successful VM-entry with the "VMCS shadowing" VM-execution
control set, the shadow VMCS referenced by the VMCS link pointer field
in the current VMCS becomes active on the logical processor.

A VMCS that is made active on more than one logical processor may become
corrupted. Therefore, before an active VMCS can be migrated to another
logical processor, the first logical processor must execute a VMCLEAR
for the active VMCS. VMCLEAR both ensures that all VMCS data are written
to memory and makes the VMCS inactive.
Signed-off-by: default avatarJim Mattson <jmattson@google.com>
Reviewed-By: default avatarDavid Matlack <dmatlack@google.com>
Message-Id: <1477668579-22555-1-git-send-email-jmattson@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
(backported from commit 355f4fb1)
[juergh:
 - Adjusted for already present alloc_loaded_vmcs().
 - Adjusted context.]
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Acked-by: default avatarStefan Bader <stefan.bader@canonical.com>
Acked-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 750d62d4
...@@ -340,6 +340,7 @@ struct vmcs { ...@@ -340,6 +340,7 @@ struct vmcs {
*/ */
struct loaded_vmcs { struct loaded_vmcs {
struct vmcs *vmcs; struct vmcs *vmcs;
struct vmcs *shadow_vmcs;
int cpu; int cpu;
int launched; int launched;
unsigned long *msr_bitmap; unsigned long *msr_bitmap;
...@@ -552,7 +553,6 @@ struct nested_vmx { ...@@ -552,7 +553,6 @@ struct nested_vmx {
/* The host-usable pointer to the above */ /* The host-usable pointer to the above */
struct page *current_vmcs12_page; struct page *current_vmcs12_page;
struct vmcs12 *current_vmcs12; struct vmcs12 *current_vmcs12;
struct vmcs *current_shadow_vmcs;
/* /*
* Indicates if the shadow vmcs must be updated with the * Indicates if the shadow vmcs must be updated with the
* data hold by vmcs12 * data hold by vmcs12
...@@ -1498,6 +1498,8 @@ static void vmcs_clear(struct vmcs *vmcs) ...@@ -1498,6 +1498,8 @@ static void vmcs_clear(struct vmcs *vmcs)
static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs) static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)
{ {
vmcs_clear(loaded_vmcs->vmcs); vmcs_clear(loaded_vmcs->vmcs);
if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
vmcs_clear(loaded_vmcs->shadow_vmcs);
loaded_vmcs->cpu = -1; loaded_vmcs->cpu = -1;
loaded_vmcs->launched = 0; loaded_vmcs->launched = 0;
} }
...@@ -3648,6 +3650,7 @@ static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs) ...@@ -3648,6 +3650,7 @@ static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
loaded_vmcs->vmcs = NULL; loaded_vmcs->vmcs = NULL;
if (loaded_vmcs->msr_bitmap) if (loaded_vmcs->msr_bitmap)
free_page((unsigned long)loaded_vmcs->msr_bitmap); free_page((unsigned long)loaded_vmcs->msr_bitmap);
WARN_ON(loaded_vmcs->shadow_vmcs != NULL);
} }
static struct vmcs *alloc_vmcs(void) static struct vmcs *alloc_vmcs(void)
...@@ -3661,6 +3664,7 @@ static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs) ...@@ -3661,6 +3664,7 @@ static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
if (!loaded_vmcs->vmcs) if (!loaded_vmcs->vmcs)
return -ENOMEM; return -ENOMEM;
loaded_vmcs->shadow_vmcs = NULL;
loaded_vmcs_init(loaded_vmcs); loaded_vmcs_init(loaded_vmcs);
if (cpu_has_vmx_msr_bitmap()) { if (cpu_has_vmx_msr_bitmap()) {
...@@ -7061,7 +7065,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu) ...@@ -7061,7 +7065,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
shadow_vmcs->revision_id |= (1u << 31); shadow_vmcs->revision_id |= (1u << 31);
/* init shadow vmcs */ /* init shadow vmcs */
vmcs_clear(shadow_vmcs); vmcs_clear(shadow_vmcs);
vmx->nested.current_shadow_vmcs = shadow_vmcs; vmx->vmcs01.shadow_vmcs = shadow_vmcs;
} }
hrtimer_init(&vmx->nested.preemption_timer, CLOCK_MONOTONIC, hrtimer_init(&vmx->nested.preemption_timer, CLOCK_MONOTONIC,
...@@ -7150,9 +7154,12 @@ static void free_nested(struct vcpu_vmx *vmx) ...@@ -7150,9 +7154,12 @@ static void free_nested(struct vcpu_vmx *vmx)
vmx->nested.vmxon = false; vmx->nested.vmxon = false;
free_vpid(vmx->nested.vpid02); free_vpid(vmx->nested.vpid02);
nested_release_vmcs12(vmx); nested_release_vmcs12(vmx);
if (enable_shadow_vmcs) if (enable_shadow_vmcs) {
free_vmcs(vmx->nested.current_shadow_vmcs); vmcs_clear(vmx->vmcs01.shadow_vmcs);
/* Unpin physical memory we referred to in the vmcs02 */ free_vmcs(vmx->vmcs01.shadow_vmcs);
vmx->vmcs01.shadow_vmcs = NULL;
}
/* Unpin physical memory we referred to in current vmcs02 */
if (vmx->nested.apic_access_page) { if (vmx->nested.apic_access_page) {
nested_release_page(vmx->nested.apic_access_page); nested_release_page(vmx->nested.apic_access_page);
vmx->nested.apic_access_page = NULL; vmx->nested.apic_access_page = NULL;
...@@ -7311,7 +7318,7 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx) ...@@ -7311,7 +7318,7 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
int i; int i;
unsigned long field; unsigned long field;
u64 field_value; u64 field_value;
struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;
const unsigned long *fields = shadow_read_write_fields; const unsigned long *fields = shadow_read_write_fields;
const int num_fields = max_shadow_read_write_fields; const int num_fields = max_shadow_read_write_fields;
...@@ -7360,7 +7367,7 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx) ...@@ -7360,7 +7367,7 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
int i, q; int i, q;
unsigned long field; unsigned long field;
u64 field_value = 0; u64 field_value = 0;
struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;
vmcs_load(shadow_vmcs); vmcs_load(shadow_vmcs);
...@@ -7543,7 +7550,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) ...@@ -7543,7 +7550,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
SECONDARY_EXEC_SHADOW_VMCS); SECONDARY_EXEC_SHADOW_VMCS);
vmcs_write64(VMCS_LINK_POINTER, vmcs_write64(VMCS_LINK_POINTER,
__pa(vmx->nested.current_shadow_vmcs)); __pa(vmx->vmcs01.shadow_vmcs));
vmx->nested.sync_shadow_vmcs = true; vmx->nested.sync_shadow_vmcs = true;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment