Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 343563
b: refs/heads/master
c: 914daba
h: refs/heads/master
i:
  343561: c755e7d
  343559: e587a09
v: v3
  • Loading branch information
Alexander Graf committed Dec 6, 2012
1 parent f08b6b3 commit 1837d0c
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 231 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8f536b7697a0d40ef6b5fd04cf2c04953d5ca06f
refs/heads/master: 914daba865cb5c38cd5fdee024ca38029315b38f
2 changes: 0 additions & 2 deletions trunk/arch/x86/include/asm/kexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ struct kimage_arch {
};
#endif

extern void (*crash_vmclear_loaded_vmcss)(void);

#endif /* __ASSEMBLY__ */

#endif /* _ASM_X86_KEXEC_H */
3 changes: 2 additions & 1 deletion trunk/arch/x86/include/asm/vmx.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ enum vmcs_field {
#define VMX_EPTP_WB_BIT (1ull << 14)
#define VMX_EPT_2MB_PAGE_BIT (1ull << 16)
#define VMX_EPT_1GB_PAGE_BIT (1ull << 17)
#define VMX_EPT_AD_BIT (1ull << 21)
#define VMX_EPT_AD_BIT (1ull << 21)
#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24)
#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25)
#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)

Expand Down
32 changes: 0 additions & 32 deletions trunk/arch/x86/kernel/crash.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <linux/delay.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/module.h>

#include <asm/processor.h>
#include <asm/hardirq.h>
Expand All @@ -31,27 +30,6 @@

int in_crash_kexec;

/*
* This is used to VMCLEAR all VMCSs loaded on the
* processor. And when loading kvm_intel module, the
* callback function pointer will be assigned.
*
* protected by rcu.
*/
void (*crash_vmclear_loaded_vmcss)(void) = NULL;
EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss);

static inline void cpu_crash_vmclear_loaded_vmcss(void)
{
void (*do_vmclear_operation)(void) = NULL;

rcu_read_lock();
do_vmclear_operation = rcu_dereference(crash_vmclear_loaded_vmcss);
if (do_vmclear_operation)
do_vmclear_operation();
rcu_read_unlock();
}

#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)

static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
Expand All @@ -68,11 +46,6 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
#endif
crash_save_cpu(regs, cpu);

/*
* VMCLEAR VMCSs loaded on all cpus if needed.
*/
cpu_crash_vmclear_loaded_vmcss();

/* Disable VMX or SVM if needed.
*
* We need to disable virtualization on all CPUs.
Expand Down Expand Up @@ -115,11 +88,6 @@ void native_machine_crash_shutdown(struct pt_regs *regs)

kdump_nmi_shootdown_cpus();

/*
* VMCLEAR VMCSs loaded on this cpu if needed.
*/
cpu_crash_vmclear_loaded_vmcss();

/* Booting kdump kernel with VMX or SVM enabled won't work,
* because (among other limitations) we can't disable paging
* with the virt flags.
Expand Down
1 change: 0 additions & 1 deletion trunk/arch/x86/kvm/cpuid.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,6 @@ void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
} else
*eax = *ebx = *ecx = *edx = 0;
}
EXPORT_SYMBOL_GPL(kvm_cpuid);

void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
{
Expand Down
16 changes: 4 additions & 12 deletions trunk/arch/x86/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2382,20 +2382,12 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
|| (!vcpu->arch.mmu.direct_map && write_fault
&& !is_write_protection(vcpu) && !user_fault)) {

/*
* There are two cases:
* - the one is other vcpu creates new sp in the window
* between mapping_level() and acquiring mmu-lock.
* - the another case is the new sp is created by itself
* (page-fault path) when guest uses the target gfn as
* its page table.
* Both of these cases can be fixed by allowing guest to
* retry the access, it will refault, then we can establish
* the mapping by using small page.
*/
if (level > PT_PAGE_TABLE_LEVEL &&
has_wrprotected_page(vcpu->kvm, gfn, level))
has_wrprotected_page(vcpu->kvm, gfn, level)) {
ret = 1;
drop_spte(vcpu->kvm, sptep);
goto done;
}

spte |= PT_WRITABLE_MASK | SPTE_MMU_WRITEABLE;

Expand Down
14 changes: 8 additions & 6 deletions trunk/arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "mmu.h"
#include "kvm_cache_regs.h"
#include "x86.h"
#include "cpuid.h"

#include <linux/module.h>
#include <linux/mod_devicetable.h>
Expand Down Expand Up @@ -1194,8 +1193,6 @@ static void init_vmcb(struct vcpu_svm *svm)
static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
u32 dummy;
u32 eax = 1;

init_vmcb(svm);

Expand All @@ -1204,9 +1201,8 @@ static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
svm->vmcb->save.cs.base = svm->vcpu.arch.sipi_vector << 12;
svm->vmcb->save.cs.selector = svm->vcpu.arch.sipi_vector << 8;
}

kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy);
kvm_register_write(vcpu, VCPU_REGS_RDX, eax);
vcpu->arch.regs_avail = ~0;
vcpu->arch.regs_dirty = ~0;

return 0;
}
Expand Down Expand Up @@ -1263,6 +1259,10 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
svm->asid_generation = 0;
init_vmcb(svm);

err = fx_init(&svm->vcpu);
if (err)
goto free_page4;

svm->vcpu.arch.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
if (kvm_vcpu_is_bsp(&svm->vcpu))
svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
Expand All @@ -1271,6 +1271,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)

return &svm->vcpu;

free_page4:
__free_page(hsave_page);
free_page3:
__free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER);
free_page2:
Expand Down
96 changes: 29 additions & 67 deletions trunk/arch/x86/kvm/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
#include <asm/i387.h>
#include <asm/xcr.h>
#include <asm/perf_event.h>
#include <asm/kexec.h>

#include "trace.h"

Expand Down Expand Up @@ -803,6 +802,11 @@ static inline bool cpu_has_vmx_ept_ad_bits(void)
return vmx_capability.ept & VMX_EPT_AD_BIT;
}

static inline bool cpu_has_vmx_invept_individual_addr(void)
{
return vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT;
}

static inline bool cpu_has_vmx_invept_context(void)
{
return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
Expand Down Expand Up @@ -988,46 +992,6 @@ static void vmcs_load(struct vmcs *vmcs)
vmcs, phys_addr);
}

#ifdef CONFIG_KEXEC
/*
* This bitmap is used to indicate whether the vmclear
* operation is enabled on all cpus. All disabled by
* default.
*/
static cpumask_t crash_vmclear_enabled_bitmap = CPU_MASK_NONE;

static inline void crash_enable_local_vmclear(int cpu)
{
cpumask_set_cpu(cpu, &crash_vmclear_enabled_bitmap);
}

static inline void crash_disable_local_vmclear(int cpu)
{
cpumask_clear_cpu(cpu, &crash_vmclear_enabled_bitmap);
}

static inline int crash_local_vmclear_enabled(int cpu)
{
return cpumask_test_cpu(cpu, &crash_vmclear_enabled_bitmap);
}

static void crash_vmclear_local_loaded_vmcss(void)
{
int cpu = raw_smp_processor_id();
struct loaded_vmcs *v;

if (!crash_local_vmclear_enabled(cpu))
return;

list_for_each_entry(v, &per_cpu(loaded_vmcss_on_cpu, cpu),
loaded_vmcss_on_cpu_link)
vmcs_clear(v->vmcs);
}
#else
static inline void crash_enable_local_vmclear(int cpu) { }
static inline void crash_disable_local_vmclear(int cpu) { }
#endif /* CONFIG_KEXEC */

static void __loaded_vmcs_clear(void *arg)
{
struct loaded_vmcs *loaded_vmcs = arg;
Expand All @@ -1037,7 +1001,6 @@ static void __loaded_vmcs_clear(void *arg)
return; /* vcpu migration can race with cpu offline */
if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
per_cpu(current_vmcs, cpu) = NULL;
crash_disable_local_vmclear(cpu);
list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);

/*
Expand All @@ -1049,7 +1012,6 @@ static void __loaded_vmcs_clear(void *arg)
smp_wmb();

loaded_vmcs_init(loaded_vmcs);
crash_enable_local_vmclear(cpu);
}

static void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
Expand Down Expand Up @@ -1100,6 +1062,17 @@ static inline void ept_sync_context(u64 eptp)
}
}

static inline void ept_sync_individual_addr(u64 eptp, gpa_t gpa)
{
if (enable_ept) {
if (cpu_has_vmx_invept_individual_addr())
__invept(VMX_EPT_EXTENT_INDIVIDUAL_ADDR,
eptp, gpa);
else
ept_sync_context(eptp);
}
}

static __always_inline unsigned long vmcs_readl(unsigned long field)
{
unsigned long value;
Expand Down Expand Up @@ -1573,7 +1546,6 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)

kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
local_irq_disable();
crash_disable_local_vmclear(cpu);

/*
* Read loaded_vmcs->cpu should be before fetching
Expand All @@ -1584,7 +1556,6 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)

list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
&per_cpu(loaded_vmcss_on_cpu, cpu));
crash_enable_local_vmclear(cpu);
local_irq_enable();

/*
Expand Down Expand Up @@ -2398,18 +2369,6 @@ static int hardware_enable(void *garbage)
return -EBUSY;

INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));

/*
* Now we can enable the vmclear operation in kdump
* since the loaded_vmcss_on_cpu list on this cpu
* has been initialized.
*
* Though the cpu is not in VMX operation now, there
* is no problem to enable the vmclear operation
* for the loaded_vmcss_on_cpu list is empty!
*/
crash_enable_local_vmclear(cpu);

rdmsrl(MSR_IA32_FEATURE_CONTROL, old);

test_bits = FEATURE_CONTROL_LOCKED;
Expand Down Expand Up @@ -3975,6 +3934,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
u64 msr;
int ret;

vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));

vmx->rmode.vm86_active = 0;

vmx->soft_vnmi_blocked = 0;
Expand All @@ -3986,6 +3947,10 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
msr |= MSR_IA32_APICBASE_BSP;
kvm_set_apic_base(&vmx->vcpu, msr);

ret = fx_init(&vmx->vcpu);
if (ret != 0)
goto out;

vmx_segment_cache_clear(vmx);

seg_setup(VCPU_SREG_CS);
Expand Down Expand Up @@ -4026,6 +3991,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
kvm_rip_write(vcpu, 0xfff0);
else
kvm_rip_write(vcpu, 0);
kvm_register_write(vcpu, VCPU_REGS_RSP, 0);

vmcs_writel(GUEST_GDTR_BASE, 0);
vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
Expand Down Expand Up @@ -4075,6 +4041,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
/* HACK: Don't enable emulation on guest boot/reset */
vmx->emulation_required = 0;

out:
return ret;
}

Expand Down Expand Up @@ -4896,6 +4863,11 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)

exit_qualification = vmcs_readl(EXIT_QUALIFICATION);

if (exit_qualification & (1 << 6)) {
printk(KERN_ERR "EPT: GPA exceeds GAW!\n");
return -EINVAL;
}

gla_validity = (exit_qualification >> 7) & 0x3;
if (gla_validity != 0x3 && gla_validity != 0x1 && gla_validity != 0) {
printk(KERN_ERR "EPT: Handling EPT violation failed!\n");
Expand Down Expand Up @@ -7440,11 +7412,6 @@ static int __init vmx_init(void)
if (r)
goto out3;

#ifdef CONFIG_KEXEC
rcu_assign_pointer(crash_vmclear_loaded_vmcss,
crash_vmclear_local_loaded_vmcss);
#endif

vmx_disable_intercept_for_msr(MSR_FS_BASE, false);
vmx_disable_intercept_for_msr(MSR_GS_BASE, false);
vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true);
Expand Down Expand Up @@ -7482,11 +7449,6 @@ static void __exit vmx_exit(void)
free_page((unsigned long)vmx_io_bitmap_b);
free_page((unsigned long)vmx_io_bitmap_a);

#ifdef CONFIG_KEXEC
rcu_assign_pointer(crash_vmclear_loaded_vmcss, NULL);
synchronize_rcu();
#endif

kvm_exit();
}

Expand Down
Loading

0 comments on commit 1837d0c

Please sign in to comment.