Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49c13b51 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm: (80 commits)
  KVM: Use CPU_DYING for disabling virtualization
  KVM: Tune hotplug/suspend IPIs
  KVM: Keep track of which cpus have virtualization enabled
  SMP: Allow smp_call_function_single() to current cpu
  i386: Allow smp_call_function_single() to current cpu
  x86_64: Allow smp_call_function_single() to current cpu
  HOTPLUG: Adapt thermal throttle to CPU_DYING
  HOTPLUG: Adapt cpuset hotplug callback to CPU_DYING
  HOTPLUG: Add CPU_DYING notifier
  KVM: Clean up #includes
  KVM: Remove kvmfs in favor of the anonymous inodes source
  KVM: SVM: Reliably detect if SVM was disabled by BIOS
  KVM: VMX: Remove unnecessary code in vmx_tlb_flush()
  KVM: MMU: Fix Wrong tlb flush order
  KVM: VMX: Reinitialize the real-mode tss when entering real mode
  KVM: Avoid useless memory write when possible
  KVM: Fix x86 emulator writeback
  KVM: Add support for in-kernel pio handlers
  KVM: VMX: Fix interrupt checking on lightweight exit
  KVM: Adds support for in-kernel mmio handlers
  ...
parents 492559af cec9ad27
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -134,19 +134,21 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
	int err;

	sys_dev = get_cpu_sysdev(cpu);
	mutex_lock(&therm_cpu_lock);
	switch (action) {
	case CPU_ONLINE:
	case CPU_ONLINE_FROZEN:
		mutex_lock(&therm_cpu_lock);
		err = thermal_throttle_add_dev(sys_dev);
		mutex_unlock(&therm_cpu_lock);
		WARN_ON(err);
		break;
	case CPU_DEAD:
	case CPU_DEAD_FROZEN:
		mutex_lock(&therm_cpu_lock);
		thermal_throttle_remove_dev(sys_dev);
		mutex_unlock(&therm_cpu_lock);
		break;
	}
	mutex_unlock(&therm_cpu_lock);
	return NOTIFY_OK;
}

+5 −3
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
EXPORT_SYMBOL(smp_call_function);

/**
 * smp_call_function_single - Run a function on another CPU
 * smp_call_function_single - Run a function on a specific CPU
 * @cpu: The target CPU.  Cannot be the calling CPU.
 * @func: The function to run. This must be fast and non-blocking.
 * @info: An arbitrary pointer to pass to the function.
@@ -66,9 +66,11 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
	int ret;
	int me = get_cpu();
	if (cpu == me) {
		WARN_ON(1);
		local_irq_disable();
		func(info);
		local_irq_enable();
		put_cpu();
		return -EBUSY;
		return 0;
	}

	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+8 −4
Original line number Diff line number Diff line
@@ -357,7 +357,7 @@ __smp_call_function_single(int cpu, void (*func) (void *info), void *info,
}

/*
 * smp_call_function_single - Run a function on another CPU
 * smp_call_function_single - Run a function on a specific CPU
 * @func: The function to run. This must be fast and non-blocking.
 * @info: An arbitrary pointer to pass to the function.
 * @nonatomic: Currently unused.
@@ -374,14 +374,18 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
{
	/* prevent preemption and reschedule on another processor */
	int me = get_cpu();

	/* Can deadlock when called with interrupts disabled */
	WARN_ON(irqs_disabled());

	if (cpu == me) {
		local_irq_disable();
		func(info);
		local_irq_enable();
		put_cpu();
		return 0;
	}

	/* Can deadlock when called with interrupts disabled */
	WARN_ON(irqs_disabled());

	spin_lock_bh(&call_lock);
	__smp_call_function_single(cpu, func, info, nonatomic, wait);
	spin_unlock_bh(&call_lock);
+7 −2
Original line number Diff line number Diff line
#
# KVM configuration
#
menu "Virtualization"
menuconfig VIRTUALIZATION
	bool "Virtualization"
	depends on X86
	default y

if VIRTUALIZATION

config KVM
	tristate "Kernel-based Virtual Machine (KVM) support"
	depends on X86 && EXPERIMENTAL
	depends on X86_CMPXCHG64 || 64BIT
	---help---
	  Support hosting fully virtualized guest machines using hardware
	  virtualization extensions.  You will need a fairly recent
@@ -35,4 +40,4 @@ config KVM_AMD
	  Provides support for KVM on AMD processors equipped with the AMD-V
	  (SVM) extensions.

endmenu
endif # VIRTUALIZATION
+108 −8
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/signal.h>

@@ -18,6 +20,7 @@
#include <linux/kvm_para.h>

#define CR0_PE_MASK (1ULL << 0)
#define CR0_MP_MASK (1ULL << 1)
#define CR0_TS_MASK (1ULL << 3)
#define CR0_NE_MASK (1ULL << 5)
#define CR0_WP_MASK (1ULL << 16)
@@ -42,7 +45,8 @@
	(CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK \
	 | CR0_NW_MASK | CR0_CD_MASK)
#define KVM_VM_CR0_ALWAYS_ON \
	(CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK)
	(CR0_PG_MASK | CR0_PE_MASK | CR0_WP_MASK | CR0_NE_MASK | CR0_TS_MASK \
	 | CR0_MP_MASK)
#define KVM_GUEST_CR4_MASK \
	(CR4_PSE_MASK | CR4_PAE_MASK | CR4_PGE_MASK | CR4_VMXE_MASK | CR4_VME_MASK)
#define KVM_PMODE_VM_CR4_ALWAYS_ON (CR4_VMXE_MASK | CR4_PAE_MASK)
@@ -51,10 +55,10 @@
#define INVALID_PAGE (~(hpa_t)0)
#define UNMAPPED_GVA (~(gpa_t)0)

#define KVM_MAX_VCPUS 1
#define KVM_MAX_VCPUS 4
#define KVM_ALIAS_SLOTS 4
#define KVM_MEMORY_SLOTS 4
#define KVM_NUM_MMU_PAGES 256
#define KVM_NUM_MMU_PAGES 1024
#define KVM_MIN_FREE_MMU_PAGES 5
#define KVM_REFILL_PAGES 25
#define KVM_MAX_CPUID_ENTRIES 40
@@ -79,6 +83,11 @@

#define KVM_PIO_PAGE_OFFSET 1

/*
 * vcpu->requests bit members
 */
#define KVM_TLB_FLUSH 0

/*
 * Address types:
 *
@@ -137,7 +146,7 @@ struct kvm_mmu_page {
	gfn_t gfn;
	union kvm_mmu_page_role role;

	hpa_t page_hpa;
	u64 *spt;
	unsigned long slot_bitmap; /* One bit set per slot which has memory
				    * in this shadow page.
				    */
@@ -232,6 +241,7 @@ struct kvm_pio_request {
	struct page *guest_pages[2];
	unsigned guest_page_offset;
	int in;
	int port;
	int size;
	int string;
	int down;
@@ -252,8 +262,70 @@ struct kvm_stat {
	u32 halt_exits;
	u32 request_irq_exits;
	u32 irq_exits;
	u32 light_exits;
	u32 efer_reload;
};

struct kvm_io_device {
	void (*read)(struct kvm_io_device *this,
		     gpa_t addr,
		     int len,
		     void *val);
	void (*write)(struct kvm_io_device *this,
		      gpa_t addr,
		      int len,
		      const void *val);
	int (*in_range)(struct kvm_io_device *this, gpa_t addr);
	void (*destructor)(struct kvm_io_device *this);

	void             *private;
};

static inline void kvm_iodevice_read(struct kvm_io_device *dev,
				     gpa_t addr,
				     int len,
				     void *val)
{
	dev->read(dev, addr, len, val);
}

static inline void kvm_iodevice_write(struct kvm_io_device *dev,
				      gpa_t addr,
				      int len,
				      const void *val)
{
	dev->write(dev, addr, len, val);
}

static inline int kvm_iodevice_inrange(struct kvm_io_device *dev, gpa_t addr)
{
	return dev->in_range(dev, addr);
}

static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
{
	if (dev->destructor)
		dev->destructor(dev);
}

/*
 * It would be nice to use something smarter than a linear search, TBD...
 * Thankfully we dont expect many devices to register (famous last words :),
 * so until then it will suffice.  At least its abstracted so we can change
 * in one place.
 */
struct kvm_io_bus {
	int                   dev_count;
#define NR_IOBUS_DEVS 6
	struct kvm_io_device *devs[NR_IOBUS_DEVS];
};

void kvm_io_bus_init(struct kvm_io_bus *bus);
void kvm_io_bus_destroy(struct kvm_io_bus *bus);
struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr);
void kvm_io_bus_register_dev(struct kvm_io_bus *bus,
			     struct kvm_io_device *dev);

struct kvm_vcpu {
	struct kvm *kvm;
	union {
@@ -266,6 +338,8 @@ struct kvm_vcpu {
	u64 host_tsc;
	struct kvm_run *run;
	int interrupt_window_open;
	int guest_mode;
	unsigned long requests;
	unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
#define NR_IRQ_WORDS KVM_IRQ_BITMAP_SIZE(unsigned long)
	unsigned long irq_pending[NR_IRQ_WORDS];
@@ -285,15 +359,20 @@ struct kvm_vcpu {
	u64 apic_base;
	u64 ia32_misc_enable_msr;
	int nmsrs;
	int save_nmsrs;
	int msr_offset_efer;
#ifdef CONFIG_X86_64
	int msr_offset_kernel_gs_base;
#endif
	struct vmx_msr_entry *guest_msrs;
	struct vmx_msr_entry *host_msrs;

	struct list_head free_pages;
	struct kvm_mmu_page page_header_buf[KVM_NUM_MMU_PAGES];
	struct kvm_mmu mmu;

	struct kvm_mmu_memory_cache mmu_pte_chain_cache;
	struct kvm_mmu_memory_cache mmu_rmap_desc_cache;
	struct kvm_mmu_memory_cache mmu_page_cache;
	struct kvm_mmu_memory_cache mmu_page_header_cache;

	gfn_t last_pt_write_gfn;
	int   last_pt_write_count;
@@ -305,6 +384,11 @@ struct kvm_vcpu {
	char *guest_fx_image;
	int fpu_active;
	int guest_fpu_loaded;
	struct vmx_host_state {
		int loaded;
		u16 fs_sel, gs_sel, ldt_sel;
		int fs_gs_ldt_reload_needed;
	} vmx_host_state;

	int mmio_needed;
	int mmio_read_completed;
@@ -331,6 +415,7 @@ struct kvm_vcpu {
			u32 ar;
		} tr, es, ds, fs, gs;
	} rmode;
	int halt_request; /* real mode on Intel only */

	int cpuid_nent;
	struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
@@ -362,12 +447,15 @@ struct kvm {
	struct list_head active_mmu_pages;
	int n_free_mmu_pages;
	struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
	int nvcpus;
	struct kvm_vcpu vcpus[KVM_MAX_VCPUS];
	int memory_config_version;
	int busy;
	unsigned long rmap_overflow;
	struct list_head vm_list;
	struct file *filp;
	struct kvm_io_bus mmio_bus;
	struct kvm_io_bus pio_bus;
};

struct descriptor_table {
@@ -488,6 +576,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
		  int size, unsigned long count, int string, int down,
		  gva_t address, int rep, unsigned port);
void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
int kvm_emulate_halt(struct kvm_vcpu *vcpu);
int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address);
int emulate_clts(struct kvm_vcpu *vcpu);
int emulator_get_dr(struct x86_emulate_ctxt* ctxt, int dr,
@@ -511,6 +600,7 @@ void save_msrs(struct vmx_msr_entry *e, int n);
void kvm_resched(struct kvm_vcpu *vcpu);
void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
void kvm_flush_remote_tlbs(struct kvm *kvm);

int kvm_read_guest(struct kvm_vcpu *vcpu,
	       gva_t addr,
@@ -524,10 +614,12 @@ int kvm_write_guest(struct kvm_vcpu *vcpu,

unsigned long segment_base(u16 selector);

void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
void kvm_mmu_post_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes);
void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
		       const u8 *old, const u8 *new, int bytes);
int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
int kvm_mmu_load(struct kvm_vcpu *vcpu);
void kvm_mmu_unload(struct kvm_vcpu *vcpu);

int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run);

@@ -539,6 +631,14 @@ static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
	return vcpu->mmu.page_fault(vcpu, gva, error_code);
}

static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu)
{
	if (likely(vcpu->mmu.root_hpa != INVALID_PAGE))
		return 0;

	return kvm_mmu_load(vcpu);
}

static inline int is_long_mode(struct kvm_vcpu *vcpu)
{
#ifdef CONFIG_X86_64
Loading