Commit b80c76ec authored by Jim Mattson's avatar Jim Mattson Committed by Radim Krčmář

KVM: VMX: Add VMCS to CPU's loaded VMCSs before VMPTRLD

Kexec needs to know the addresses of all VMCSs that are active on
each CPU, so that it can flush them from the VMCS caches. It is
safe to record superfluous addresses that are not associated with
an active VMCS, but it is not safe to omit an address associated
with an active VMCS.

After a call to vmcs_load, the VMCS that was loaded is active on
the CPU. The VMCS should be added to the CPU's list of active
VMCSs before it is loaded.
Signed-off-by: default avatarJim Mattson <jmattson@google.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent 4f2777bc
...@@ -2205,22 +2205,14 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) ...@@ -2205,22 +2205,14 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
bool already_loaded = vmx->loaded_vmcs->cpu == cpu;
if (!vmm_exclusive) if (!vmm_exclusive)
kvm_cpu_vmxon(phys_addr); kvm_cpu_vmxon(phys_addr);
else if (vmx->loaded_vmcs->cpu != cpu) else if (!already_loaded)
loaded_vmcs_clear(vmx->loaded_vmcs); loaded_vmcs_clear(vmx->loaded_vmcs);
if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) { if (!already_loaded) {
per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
vmcs_load(vmx->loaded_vmcs->vmcs);
}
if (vmx->loaded_vmcs->cpu != cpu) {
struct desc_ptr *gdt = this_cpu_ptr(&host_gdt);
unsigned long sysenter_esp;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
local_irq_disable(); local_irq_disable();
crash_disable_local_vmclear(cpu); crash_disable_local_vmclear(cpu);
...@@ -2235,6 +2227,18 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) ...@@ -2235,6 +2227,18 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
&per_cpu(loaded_vmcss_on_cpu, cpu)); &per_cpu(loaded_vmcss_on_cpu, cpu));
crash_enable_local_vmclear(cpu); crash_enable_local_vmclear(cpu);
local_irq_enable(); local_irq_enable();
}
if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
vmcs_load(vmx->loaded_vmcs->vmcs);
}
if (!already_loaded) {
struct desc_ptr *gdt = this_cpu_ptr(&host_gdt);
unsigned long sysenter_esp;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
/* /*
* Linux uses per-cpu TSS and GDT, so set these when switching * Linux uses per-cpu TSS and GDT, so set these when switching
......
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