mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge branch 'kvm-updates-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm
* 'kvm-updates-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm: (70 commits) KVM: Adjust smp_call_function_mask() callers to new requirements KVM: MMU: Fix potential race setting upper shadow ptes on nonpae hosts KVM: x86 emulator: emulate clflush KVM: MMU: improve invalid shadow root page handling KVM: MMU: nuke shadowed pgtable pages and ptes on memslot destruction KVM: Prefix some x86 low level function with kvm_, to avoid namespace issues KVM: check injected pic irq within valid pic irqs KVM: x86 emulator: Fix HLT instruction KVM: Apply the kernel sigmask to vcpus blocked due to being uninitialized KVM: VMX: Add ept_sync_context in flush_tlb KVM: mmu_shrink: kvm_mmu_zap_page requires slots_lock to be held x86: KVM guest: make kvm_smp_prepare_boot_cpu() static KVM: SVM: fix suspend/resume support KVM: s390: rename private structures KVM: s390: Set guest storage limit and offset to sane values KVM: Fix memory leak on guest exit KVM: s390: dont allocate dirty bitmap KVM: move slots_lock acquision down to vapic_exit KVM: VMX: Fake emulate Intel perfctr MSRs KVM: VMX: Fix a wrong usage of vmcs_config ...
This commit is contained in:
@@ -43,7 +43,8 @@ $(obj)/$(offsets-file): arch/ia64/kvm/asm-offsets.s
|
||||
EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
|
||||
EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
|
||||
|
||||
common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o)
|
||||
common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
|
||||
coalesced_mmio.o)
|
||||
|
||||
kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
|
||||
@@ -187,6 +187,9 @@ int kvm_dev_ioctl_check_extension(long ext)
|
||||
|
||||
r = 1;
|
||||
break;
|
||||
case KVM_CAP_COALESCED_MMIO:
|
||||
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
}
|
||||
@@ -195,11 +198,11 @@ int kvm_dev_ioctl_check_extension(long ext)
|
||||
}
|
||||
|
||||
static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
|
||||
gpa_t addr)
|
||||
gpa_t addr, int len, int is_write)
|
||||
{
|
||||
struct kvm_io_device *dev;
|
||||
|
||||
dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
|
||||
dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr, len, is_write);
|
||||
|
||||
return dev;
|
||||
}
|
||||
@@ -231,7 +234,7 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
kvm_run->exit_reason = KVM_EXIT_MMIO;
|
||||
return 0;
|
||||
mmio:
|
||||
mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr);
|
||||
mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr, p->size, !p->dir);
|
||||
if (mmio_dev) {
|
||||
if (!p->dir)
|
||||
kvm_iodevice_write(mmio_dev, p->addr, p->size,
|
||||
@@ -1035,14 +1038,6 @@ static void kvm_free_vmm_area(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that a cpu that is being hot-unplugged does not have any vcpus
|
||||
* cached on it. Leave it as blank for IA64.
|
||||
*/
|
||||
void decache_vcpus_on_cpu(int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static void vti_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
{
|
||||
}
|
||||
@@ -1460,6 +1455,9 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_flush_shadow(struct kvm *kvm)
|
||||
{
|
||||
}
|
||||
|
||||
long kvm_arch_dev_ioctl(struct file *filp,
|
||||
unsigned int ioctl, unsigned long arg)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
|
||||
|
||||
common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
|
||||
common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
|
||||
|
||||
kvm-objs := $(common-objs) powerpc.o emulate.o booke_guest.o
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
|
||||
@@ -145,6 +145,9 @@ int kvm_dev_ioctl_check_extension(long ext)
|
||||
case KVM_CAP_USER_MEMORY:
|
||||
r = 1;
|
||||
break;
|
||||
case KVM_CAP_COALESCED_MMIO:
|
||||
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
break;
|
||||
@@ -167,6 +170,10 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_flush_shadow(struct kvm *kvm)
|
||||
{
|
||||
}
|
||||
|
||||
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
|
||||
{
|
||||
struct kvm_vcpu *vcpu;
|
||||
@@ -240,10 +247,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
}
|
||||
|
||||
void decache_vcpus_on_cpu(int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
|
||||
struct kvm_debug_guest *dbg)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
|
||||
struct interrupt_info *inti)
|
||||
struct kvm_s390_interrupt_info *inti)
|
||||
{
|
||||
switch (inti->type) {
|
||||
case KVM_S390_INT_EMERGENCY:
|
||||
@@ -91,7 +91,7 @@ static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
|
||||
}
|
||||
|
||||
static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
|
||||
struct interrupt_info *inti)
|
||||
struct kvm_s390_interrupt_info *inti)
|
||||
{
|
||||
switch (inti->type) {
|
||||
case KVM_S390_INT_EMERGENCY:
|
||||
@@ -111,7 +111,7 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
|
||||
}
|
||||
|
||||
static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
||||
struct interrupt_info *inti)
|
||||
struct kvm_s390_interrupt_info *inti)
|
||||
{
|
||||
const unsigned short table[] = { 2, 4, 4, 6 };
|
||||
int rc, exception = 0;
|
||||
@@ -290,9 +290,9 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
|
||||
|
||||
int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct local_interrupt *li = &vcpu->arch.local_int;
|
||||
struct float_interrupt *fi = vcpu->arch.local_int.float_int;
|
||||
struct interrupt_info *inti;
|
||||
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
|
||||
struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
int rc = 0;
|
||||
|
||||
if (atomic_read(&li->active)) {
|
||||
@@ -408,9 +408,9 @@ void kvm_s390_idle_wakeup(unsigned long data)
|
||||
|
||||
void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct local_interrupt *li = &vcpu->arch.local_int;
|
||||
struct float_interrupt *fi = vcpu->arch.local_int.float_int;
|
||||
struct interrupt_info *n, *inti = NULL;
|
||||
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
|
||||
struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
|
||||
struct kvm_s390_interrupt_info *n, *inti = NULL;
|
||||
int deliver;
|
||||
|
||||
__reset_intercept_indicators(vcpu);
|
||||
@@ -465,8 +465,8 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
|
||||
|
||||
int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
|
||||
{
|
||||
struct local_interrupt *li = &vcpu->arch.local_int;
|
||||
struct interrupt_info *inti;
|
||||
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
|
||||
inti = kzalloc(sizeof(*inti), GFP_KERNEL);
|
||||
if (!inti)
|
||||
@@ -487,9 +487,9 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
|
||||
int kvm_s390_inject_vm(struct kvm *kvm,
|
||||
struct kvm_s390_interrupt *s390int)
|
||||
{
|
||||
struct local_interrupt *li;
|
||||
struct float_interrupt *fi;
|
||||
struct interrupt_info *inti;
|
||||
struct kvm_s390_local_interrupt *li;
|
||||
struct kvm_s390_float_interrupt *fi;
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
int sigcpu;
|
||||
|
||||
inti = kzalloc(sizeof(*inti), GFP_KERNEL);
|
||||
@@ -544,8 +544,8 @@ int kvm_s390_inject_vm(struct kvm *kvm,
|
||||
int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
|
||||
struct kvm_s390_interrupt *s390int)
|
||||
{
|
||||
struct local_interrupt *li;
|
||||
struct interrupt_info *inti;
|
||||
struct kvm_s390_local_interrupt *li;
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
|
||||
inti = kzalloc(sizeof(*inti), GFP_KERNEL);
|
||||
if (!inti)
|
||||
|
||||
@@ -79,10 +79,6 @@ void kvm_arch_hardware_disable(void *garbage)
|
||||
{
|
||||
}
|
||||
|
||||
void decache_vcpus_on_cpu(int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_arch_hardware_setup(void)
|
||||
{
|
||||
return 0;
|
||||
@@ -198,6 +194,7 @@ out_nokvm:
|
||||
void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
{
|
||||
debug_unregister(kvm->arch.dbf);
|
||||
kvm_free_physmem(kvm);
|
||||
free_page((unsigned long)(kvm->arch.sca));
|
||||
kfree(kvm);
|
||||
module_put(THIS_MODULE);
|
||||
@@ -250,11 +247,16 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.sie_block->gbea = 1;
|
||||
}
|
||||
|
||||
/* The current code can have up to 256 pages for virtio */
|
||||
#define VIRTIODESCSPACE (256ul * 4096ul)
|
||||
|
||||
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
|
||||
vcpu->arch.sie_block->gmslm = 0xffffffffffUL;
|
||||
vcpu->arch.sie_block->gmsor = 0x000000000000;
|
||||
vcpu->arch.sie_block->gmslm = vcpu->kvm->arch.guest_memsize +
|
||||
vcpu->kvm->arch.guest_origin +
|
||||
VIRTIODESCSPACE - 1ul;
|
||||
vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin;
|
||||
vcpu->arch.sie_block->ecb = 2;
|
||||
vcpu->arch.sie_block->eca = 0xC1002001U;
|
||||
setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
|
||||
@@ -273,7 +275,8 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
|
||||
if (!vcpu)
|
||||
goto out_nomem;
|
||||
|
||||
vcpu->arch.sie_block = (struct sie_block *) get_zeroed_page(GFP_KERNEL);
|
||||
vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
|
||||
get_zeroed_page(GFP_KERNEL);
|
||||
|
||||
if (!vcpu->arch.sie_block)
|
||||
goto out_free_cpu;
|
||||
@@ -672,6 +675,10 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_flush_shadow(struct kvm *kvm)
|
||||
{
|
||||
}
|
||||
|
||||
gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
|
||||
{
|
||||
return gfn;
|
||||
|
||||
@@ -199,7 +199,7 @@ out:
|
||||
|
||||
static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
|
||||
{
|
||||
struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
int cpus = 0;
|
||||
int n;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg)
|
||||
{
|
||||
struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
int rc;
|
||||
|
||||
if (cpu_addr >= KVM_MAX_VCPUS)
|
||||
@@ -71,9 +71,9 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg)
|
||||
|
||||
static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
|
||||
{
|
||||
struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct local_interrupt *li;
|
||||
struct interrupt_info *inti;
|
||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct kvm_s390_local_interrupt *li;
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
int rc;
|
||||
|
||||
if (cpu_addr >= KVM_MAX_VCPUS)
|
||||
@@ -108,9 +108,9 @@ unlock:
|
||||
|
||||
static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int store)
|
||||
{
|
||||
struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct local_interrupt *li;
|
||||
struct interrupt_info *inti;
|
||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct kvm_s390_local_interrupt *li;
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
int rc;
|
||||
|
||||
if (cpu_addr >= KVM_MAX_VCPUS)
|
||||
@@ -169,9 +169,9 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
|
||||
static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
|
||||
u64 *reg)
|
||||
{
|
||||
struct float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct local_interrupt *li;
|
||||
struct interrupt_info *inti;
|
||||
struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
|
||||
struct kvm_s390_local_interrupt *li;
|
||||
struct kvm_s390_interrupt_info *inti;
|
||||
int rc;
|
||||
u8 tmp;
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ static void kvm_setup_secondary_clock(void)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void __init kvm_smp_prepare_boot_cpu(void)
|
||||
static void __init kvm_smp_prepare_boot_cpu(void)
|
||||
{
|
||||
WARN_ON(kvm_register_clock("primary cpu clock"));
|
||||
native_smp_prepare_boot_cpu();
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Makefile for Kernel-based Virtual Machine module
|
||||
#
|
||||
|
||||
common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o)
|
||||
common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
|
||||
coalesced_mmio.o)
|
||||
ifeq ($(CONFIG_KVM_TRACE),y)
|
||||
common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o)
|
||||
endif
|
||||
|
||||
@@ -91,7 +91,7 @@ static void pit_set_gate(struct kvm *kvm, int channel, u32 val)
|
||||
c->gate = val;
|
||||
}
|
||||
|
||||
int pit_get_gate(struct kvm *kvm, int channel)
|
||||
static int pit_get_gate(struct kvm *kvm, int channel)
|
||||
{
|
||||
WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
|
||||
|
||||
@@ -193,19 +193,16 @@ static void pit_latch_status(struct kvm *kvm, int channel)
|
||||
}
|
||||
}
|
||||
|
||||
int __pit_timer_fn(struct kvm_kpit_state *ps)
|
||||
static int __pit_timer_fn(struct kvm_kpit_state *ps)
|
||||
{
|
||||
struct kvm_vcpu *vcpu0 = ps->pit->kvm->vcpus[0];
|
||||
struct kvm_kpit_timer *pt = &ps->pit_timer;
|
||||
|
||||
atomic_inc(&pt->pending);
|
||||
smp_mb__after_atomic_inc();
|
||||
if (vcpu0) {
|
||||
if (!atomic_inc_and_test(&pt->pending))
|
||||
set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
|
||||
if (waitqueue_active(&vcpu0->wq)) {
|
||||
vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
|
||||
wake_up_interruptible(&vcpu0->wq);
|
||||
}
|
||||
if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
|
||||
vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
|
||||
wake_up_interruptible(&vcpu0->wq);
|
||||
}
|
||||
|
||||
pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
|
||||
@@ -308,6 +305,7 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
|
||||
create_pit_timer(&ps->pit_timer, val, 0);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
create_pit_timer(&ps->pit_timer, val, 1);
|
||||
break;
|
||||
default:
|
||||
@@ -459,7 +457,8 @@ static void pit_ioport_read(struct kvm_io_device *this,
|
||||
mutex_unlock(&pit_state->lock);
|
||||
}
|
||||
|
||||
static int pit_in_range(struct kvm_io_device *this, gpa_t addr)
|
||||
static int pit_in_range(struct kvm_io_device *this, gpa_t addr,
|
||||
int len, int is_write)
|
||||
{
|
||||
return ((addr >= KVM_PIT_BASE_ADDRESS) &&
|
||||
(addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH));
|
||||
@@ -500,7 +499,8 @@ static void speaker_ioport_read(struct kvm_io_device *this,
|
||||
mutex_unlock(&pit_state->lock);
|
||||
}
|
||||
|
||||
static int speaker_in_range(struct kvm_io_device *this, gpa_t addr)
|
||||
static int speaker_in_range(struct kvm_io_device *this, gpa_t addr,
|
||||
int len, int is_write)
|
||||
{
|
||||
return (addr == KVM_SPEAKER_BASE_ADDRESS);
|
||||
}
|
||||
@@ -575,7 +575,7 @@ void kvm_free_pit(struct kvm *kvm)
|
||||
}
|
||||
}
|
||||
|
||||
void __inject_pit_timer_intr(struct kvm *kvm)
|
||||
static void __inject_pit_timer_intr(struct kvm *kvm)
|
||||
{
|
||||
mutex_lock(&kvm->lock);
|
||||
kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 1);
|
||||
|
||||
@@ -130,8 +130,10 @@ void kvm_pic_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
struct kvm_pic *s = opaque;
|
||||
|
||||
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
|
||||
pic_update_irq(s);
|
||||
if (irq >= 0 && irq < PIC_NUM_PINS) {
|
||||
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
|
||||
pic_update_irq(s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -346,7 +348,8 @@ static u32 elcr_ioport_read(void *opaque, u32 addr1)
|
||||
return s->elcr;
|
||||
}
|
||||
|
||||
static int picdev_in_range(struct kvm_io_device *this, gpa_t addr)
|
||||
static int picdev_in_range(struct kvm_io_device *this, gpa_t addr,
|
||||
int len, int is_write)
|
||||
{
|
||||
switch (addr) {
|
||||
case 0x20:
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "ioapic.h"
|
||||
#include "lapic.h"
|
||||
|
||||
#define PIC_NUM_PINS 16
|
||||
|
||||
struct kvm;
|
||||
struct kvm_vcpu;
|
||||
|
||||
|
||||
@@ -356,8 +356,9 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
|
||||
case APIC_DM_SMI:
|
||||
printk(KERN_DEBUG "Ignoring guest SMI\n");
|
||||
break;
|
||||
|
||||
case APIC_DM_NMI:
|
||||
printk(KERN_DEBUG "Ignoring guest NMI\n");
|
||||
kvm_inject_nmi(vcpu);
|
||||
break;
|
||||
|
||||
case APIC_DM_INIT:
|
||||
@@ -572,6 +573,8 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
KVMTRACE_1D(APIC_ACCESS, apic->vcpu, (u32)offset, handler);
|
||||
|
||||
if (offset >= LAPIC_MMIO_LENGTH)
|
||||
return 0;
|
||||
|
||||
@@ -695,6 +698,8 @@ static void apic_mmio_write(struct kvm_io_device *this,
|
||||
|
||||
offset &= 0xff0;
|
||||
|
||||
KVMTRACE_1D(APIC_ACCESS, apic->vcpu, (u32)offset, handler);
|
||||
|
||||
switch (offset) {
|
||||
case APIC_ID: /* Local APIC ID */
|
||||
apic_set_reg(apic, APIC_ID, val);
|
||||
@@ -780,7 +785,8 @@ static void apic_mmio_write(struct kvm_io_device *this,
|
||||
|
||||
}
|
||||
|
||||
static int apic_mmio_range(struct kvm_io_device *this, gpa_t addr)
|
||||
static int apic_mmio_range(struct kvm_io_device *this, gpa_t addr,
|
||||
int len, int size)
|
||||
{
|
||||
struct kvm_lapic *apic = (struct kvm_lapic *)this->private;
|
||||
int ret = 0;
|
||||
@@ -939,8 +945,8 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
|
||||
int result = 0;
|
||||
wait_queue_head_t *q = &apic->vcpu->wq;
|
||||
|
||||
atomic_inc(&apic->timer.pending);
|
||||
set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
|
||||
if(!atomic_inc_and_test(&apic->timer.pending))
|
||||
set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
|
||||
if (waitqueue_active(q)) {
|
||||
apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
|
||||
wake_up_interruptible(q);
|
||||
|
||||
@@ -31,6 +31,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu);
|
||||
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
|
||||
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
|
||||
void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
|
||||
u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
|
||||
|
||||
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
|
||||
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
|
||||
|
||||
@@ -66,7 +66,8 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg) {}
|
||||
#endif
|
||||
|
||||
#if defined(MMU_DEBUG) || defined(AUDIT)
|
||||
static int dbg = 1;
|
||||
static int dbg = 0;
|
||||
module_param(dbg, bool, 0644);
|
||||
#endif
|
||||
|
||||
#ifndef MMU_DEBUG
|
||||
@@ -776,6 +777,15 @@ static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp,
|
||||
BUG();
|
||||
}
|
||||
|
||||
static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
|
||||
struct kvm_mmu_page *sp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
|
||||
sp->spt[i] = shadow_trap_nonpresent_pte;
|
||||
}
|
||||
|
||||
static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
|
||||
{
|
||||
unsigned index;
|
||||
@@ -841,7 +851,10 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
|
||||
hlist_add_head(&sp->hash_link, bucket);
|
||||
if (!metaphysical)
|
||||
rmap_write_protect(vcpu->kvm, gfn);
|
||||
vcpu->arch.mmu.prefetch_page(vcpu, sp);
|
||||
if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte)
|
||||
vcpu->arch.mmu.prefetch_page(vcpu, sp);
|
||||
else
|
||||
nonpaging_prefetch_page(vcpu, sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
@@ -917,14 +930,17 @@ static void kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
|
||||
}
|
||||
kvm_mmu_page_unlink_children(kvm, sp);
|
||||
if (!sp->root_count) {
|
||||
if (!sp->role.metaphysical)
|
||||
if (!sp->role.metaphysical && !sp->role.invalid)
|
||||
unaccount_shadowed(kvm, sp->gfn);
|
||||
hlist_del(&sp->hash_link);
|
||||
kvm_mmu_free_page(kvm, sp);
|
||||
} else {
|
||||
int invalid = sp->role.invalid;
|
||||
list_move(&sp->link, &kvm->arch.active_mmu_pages);
|
||||
sp->role.invalid = 1;
|
||||
kvm_reload_remote_mmus(kvm);
|
||||
if (!sp->role.metaphysical && !invalid)
|
||||
unaccount_shadowed(kvm, sp->gfn);
|
||||
}
|
||||
kvm_mmu_reset_last_pte_updated(kvm);
|
||||
}
|
||||
@@ -1103,7 +1119,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
|
||||
mark_page_dirty(vcpu->kvm, gfn);
|
||||
|
||||
pgprintk("%s: setting spte %llx\n", __func__, spte);
|
||||
pgprintk("instantiating %s PTE (%s) at %d (%llx) addr %llx\n",
|
||||
pgprintk("instantiating %s PTE (%s) at %ld (%llx) addr %p\n",
|
||||
(spte&PT_PAGE_SIZE_MASK)? "2MB" : "4kB",
|
||||
(spte&PT_WRITABLE_MASK)?"RW":"R", gfn, spte, shadow_pte);
|
||||
set_shadow_pte(shadow_pte, spte);
|
||||
@@ -1122,8 +1138,10 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
|
||||
else
|
||||
kvm_release_pfn_clean(pfn);
|
||||
}
|
||||
if (!ptwrite || !*ptwrite)
|
||||
if (speculative) {
|
||||
vcpu->arch.last_pte_updated = shadow_pte;
|
||||
vcpu->arch.last_pte_gfn = gfn;
|
||||
}
|
||||
}
|
||||
|
||||
static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
|
||||
@@ -1171,9 +1189,10 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
table[index] = __pa(new_table->spt)
|
||||
| PT_PRESENT_MASK | PT_WRITABLE_MASK
|
||||
| shadow_user_mask | shadow_x_mask;
|
||||
set_shadow_pte(&table[index],
|
||||
__pa(new_table->spt)
|
||||
| PT_PRESENT_MASK | PT_WRITABLE_MASK
|
||||
| shadow_user_mask | shadow_x_mask);
|
||||
}
|
||||
table_addr = table[index] & PT64_BASE_ADDR_MASK;
|
||||
}
|
||||
@@ -1211,15 +1230,6 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
|
||||
}
|
||||
|
||||
|
||||
static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
|
||||
struct kvm_mmu_page *sp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
|
||||
sp->spt[i] = shadow_trap_nonpresent_pte;
|
||||
}
|
||||
|
||||
static void mmu_free_roots(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int i;
|
||||
@@ -1671,6 +1681,18 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
vcpu->arch.update_pte.pfn = pfn;
|
||||
}
|
||||
|
||||
static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn)
|
||||
{
|
||||
u64 *spte = vcpu->arch.last_pte_updated;
|
||||
|
||||
if (spte
|
||||
&& vcpu->arch.last_pte_gfn == gfn
|
||||
&& shadow_accessed_mask
|
||||
&& !(*spte & shadow_accessed_mask)
|
||||
&& is_shadow_present_pte(*spte))
|
||||
set_bit(PT_ACCESSED_SHIFT, (unsigned long *)spte);
|
||||
}
|
||||
|
||||
void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
const u8 *new, int bytes)
|
||||
{
|
||||
@@ -1694,6 +1716,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
|
||||
mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes);
|
||||
spin_lock(&vcpu->kvm->mmu_lock);
|
||||
kvm_mmu_access_page(vcpu, gfn);
|
||||
kvm_mmu_free_some_pages(vcpu);
|
||||
++vcpu->kvm->stat.mmu_pte_write;
|
||||
kvm_mmu_audit(vcpu, "pre pte write");
|
||||
@@ -1948,7 +1971,7 @@ void kvm_mmu_zap_all(struct kvm *kvm)
|
||||
kvm_flush_remote_tlbs(kvm);
|
||||
}
|
||||
|
||||
void kvm_mmu_remove_one_alloc_mmu_page(struct kvm *kvm)
|
||||
static void kvm_mmu_remove_one_alloc_mmu_page(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_mmu_page *page;
|
||||
|
||||
@@ -1968,6 +1991,8 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask)
|
||||
list_for_each_entry(kvm, &vm_list, vm_list) {
|
||||
int npages;
|
||||
|
||||
if (!down_read_trylock(&kvm->slots_lock))
|
||||
continue;
|
||||
spin_lock(&kvm->mmu_lock);
|
||||
npages = kvm->arch.n_alloc_mmu_pages -
|
||||
kvm->arch.n_free_mmu_pages;
|
||||
@@ -1980,6 +2005,7 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask)
|
||||
nr_to_scan--;
|
||||
|
||||
spin_unlock(&kvm->mmu_lock);
|
||||
up_read(&kvm->slots_lock);
|
||||
}
|
||||
if (kvm_freed)
|
||||
list_move_tail(&kvm_freed->vm_list, &vm_list);
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#define PT_USER_MASK (1ULL << 2)
|
||||
#define PT_PWT_MASK (1ULL << 3)
|
||||
#define PT_PCD_MASK (1ULL << 4)
|
||||
#define PT_ACCESSED_MASK (1ULL << 5)
|
||||
#define PT_ACCESSED_SHIFT 5
|
||||
#define PT_ACCESSED_MASK (1ULL << PT_ACCESSED_SHIFT)
|
||||
#define PT_DIRTY_MASK (1ULL << 6)
|
||||
#define PT_PAGE_SIZE_MASK (1ULL << 7)
|
||||
#define PT_PAT_MASK (1ULL << 7)
|
||||
|
||||
@@ -460,8 +460,9 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
|
||||
static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
|
||||
struct kvm_mmu_page *sp)
|
||||
{
|
||||
int i, offset = 0, r = 0;
|
||||
pt_element_t pt;
|
||||
int i, j, offset, r;
|
||||
pt_element_t pt[256 / sizeof(pt_element_t)];
|
||||
gpa_t pte_gpa;
|
||||
|
||||
if (sp->role.metaphysical
|
||||
|| (PTTYPE == 32 && sp->role.level > PT_PAGE_TABLE_LEVEL)) {
|
||||
@@ -469,19 +470,20 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
|
||||
return;
|
||||
}
|
||||
|
||||
if (PTTYPE == 32)
|
||||
pte_gpa = gfn_to_gpa(sp->gfn);
|
||||
if (PTTYPE == 32) {
|
||||
offset = sp->role.quadrant << PT64_LEVEL_BITS;
|
||||
pte_gpa += offset * sizeof(pt_element_t);
|
||||
}
|
||||
|
||||
for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
|
||||
gpa_t pte_gpa = gfn_to_gpa(sp->gfn);
|
||||
pte_gpa += (i+offset) * sizeof(pt_element_t);
|
||||
|
||||
r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &pt,
|
||||
sizeof(pt_element_t));
|
||||
if (r || is_present_pte(pt))
|
||||
sp->spt[i] = shadow_trap_nonpresent_pte;
|
||||
else
|
||||
sp->spt[i] = shadow_notrap_nonpresent_pte;
|
||||
for (i = 0; i < PT64_ENT_PER_PAGE; i += ARRAY_SIZE(pt)) {
|
||||
r = kvm_read_guest_atomic(vcpu->kvm, pte_gpa, pt, sizeof pt);
|
||||
pte_gpa += ARRAY_SIZE(pt) * sizeof(pt_element_t);
|
||||
for (j = 0; j < ARRAY_SIZE(pt); ++j)
|
||||
if (r || is_present_pte(pt[j]))
|
||||
sp->spt[i+j] = shadow_trap_nonpresent_pte;
|
||||
else
|
||||
sp->spt[i+j] = shadow_notrap_nonpresent_pte;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include <asm/desc.h>
|
||||
|
||||
#define __ex(x) __kvm_handle_fault_on_reboot(x)
|
||||
|
||||
MODULE_AUTHOR("Qumranet");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -129,17 +131,17 @@ static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq)
|
||||
|
||||
static inline void clgi(void)
|
||||
{
|
||||
asm volatile (SVM_CLGI);
|
||||
asm volatile (__ex(SVM_CLGI));
|
||||
}
|
||||
|
||||
static inline void stgi(void)
|
||||
{
|
||||
asm volatile (SVM_STGI);
|
||||
asm volatile (__ex(SVM_STGI));
|
||||
}
|
||||
|
||||
static inline void invlpga(unsigned long addr, u32 asid)
|
||||
{
|
||||
asm volatile (SVM_INVLPGA :: "a"(addr), "c"(asid));
|
||||
asm volatile (__ex(SVM_INVLPGA) :: "a"(addr), "c"(asid));
|
||||
}
|
||||
|
||||
static inline unsigned long kvm_read_cr2(void)
|
||||
@@ -270,19 +272,11 @@ static int has_svm(void)
|
||||
|
||||
static void svm_hardware_disable(void *garbage)
|
||||
{
|
||||
struct svm_cpu_data *svm_data
|
||||
= per_cpu(svm_data, raw_smp_processor_id());
|
||||
uint64_t efer;
|
||||
|
||||
if (svm_data) {
|
||||
uint64_t efer;
|
||||
|
||||
wrmsrl(MSR_VM_HSAVE_PA, 0);
|
||||
rdmsrl(MSR_EFER, efer);
|
||||
wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
|
||||
per_cpu(svm_data, raw_smp_processor_id()) = NULL;
|
||||
__free_page(svm_data->save_area);
|
||||
kfree(svm_data);
|
||||
}
|
||||
wrmsrl(MSR_VM_HSAVE_PA, 0);
|
||||
rdmsrl(MSR_EFER, efer);
|
||||
wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
|
||||
}
|
||||
|
||||
static void svm_hardware_enable(void *garbage)
|
||||
@@ -321,6 +315,19 @@ static void svm_hardware_enable(void *garbage)
|
||||
page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static void svm_cpu_uninit(int cpu)
|
||||
{
|
||||
struct svm_cpu_data *svm_data
|
||||
= per_cpu(svm_data, raw_smp_processor_id());
|
||||
|
||||
if (!svm_data)
|
||||
return;
|
||||
|
||||
per_cpu(svm_data, raw_smp_processor_id()) = NULL;
|
||||
__free_page(svm_data->save_area);
|
||||
kfree(svm_data);
|
||||
}
|
||||
|
||||
static int svm_cpu_init(int cpu)
|
||||
{
|
||||
struct svm_cpu_data *svm_data;
|
||||
@@ -458,6 +465,11 @@ err:
|
||||
|
||||
static __exit void svm_hardware_unsetup(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
svm_cpu_uninit(cpu);
|
||||
|
||||
__free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
|
||||
iopm_base = 0;
|
||||
}
|
||||
@@ -707,10 +719,6 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
rdtscll(vcpu->arch.host_tsc);
|
||||
}
|
||||
|
||||
static void svm_vcpu_decache(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
}
|
||||
|
||||
static void svm_cache_regs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
@@ -949,7 +957,9 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data)
|
||||
|
||||
static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr)
|
||||
{
|
||||
return to_svm(vcpu)->db_regs[dr];
|
||||
unsigned long val = to_svm(vcpu)->db_regs[dr];
|
||||
KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
|
||||
@@ -1004,6 +1014,16 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
|
||||
fault_address = svm->vmcb->control.exit_info_2;
|
||||
error_code = svm->vmcb->control.exit_info_1;
|
||||
|
||||
if (!npt_enabled)
|
||||
KVMTRACE_3D(PAGE_FAULT, &svm->vcpu, error_code,
|
||||
(u32)fault_address, (u32)(fault_address >> 32),
|
||||
handler);
|
||||
else
|
||||
KVMTRACE_3D(TDP_FAULT, &svm->vcpu, error_code,
|
||||
(u32)fault_address, (u32)(fault_address >> 32),
|
||||
handler);
|
||||
|
||||
return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
|
||||
}
|
||||
|
||||
@@ -1081,6 +1101,19 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
return kvm_emulate_pio(&svm->vcpu, kvm_run, in, size, port);
|
||||
}
|
||||
|
||||
static int nmi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
{
|
||||
KVMTRACE_0D(NMI, &svm->vcpu, handler);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int intr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
{
|
||||
++svm->vcpu.stat.irq_exits;
|
||||
KVMTRACE_0D(INTR, &svm->vcpu, handler);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nop_on_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
{
|
||||
return 1;
|
||||
@@ -1219,6 +1252,9 @@ static int rdmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
if (svm_get_msr(&svm->vcpu, ecx, &data))
|
||||
kvm_inject_gp(&svm->vcpu, 0);
|
||||
else {
|
||||
KVMTRACE_3D(MSR_READ, &svm->vcpu, ecx, (u32)data,
|
||||
(u32)(data >> 32), handler);
|
||||
|
||||
svm->vmcb->save.rax = data & 0xffffffff;
|
||||
svm->vcpu.arch.regs[VCPU_REGS_RDX] = data >> 32;
|
||||
svm->next_rip = svm->vmcb->save.rip + 2;
|
||||
@@ -1284,16 +1320,19 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
|
||||
case MSR_K7_EVNTSEL1:
|
||||
case MSR_K7_EVNTSEL2:
|
||||
case MSR_K7_EVNTSEL3:
|
||||
case MSR_K7_PERFCTR0:
|
||||
case MSR_K7_PERFCTR1:
|
||||
case MSR_K7_PERFCTR2:
|
||||
case MSR_K7_PERFCTR3:
|
||||
/*
|
||||
* only support writing 0 to the performance counters for now
|
||||
* to make Windows happy. Should be replaced by a real
|
||||
* performance counter emulation later.
|
||||
* Just discard all writes to the performance counters; this
|
||||
* should keep both older linux and windows 64-bit guests
|
||||
* happy
|
||||
*/
|
||||
if (data != 0)
|
||||
goto unhandled;
|
||||
pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", ecx, data);
|
||||
|
||||
break;
|
||||
default:
|
||||
unhandled:
|
||||
return kvm_set_msr_common(vcpu, ecx, data);
|
||||
}
|
||||
return 0;
|
||||
@@ -1304,6 +1343,10 @@ static int wrmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
u32 ecx = svm->vcpu.arch.regs[VCPU_REGS_RCX];
|
||||
u64 data = (svm->vmcb->save.rax & -1u)
|
||||
| ((u64)(svm->vcpu.arch.regs[VCPU_REGS_RDX] & -1u) << 32);
|
||||
|
||||
KVMTRACE_3D(MSR_WRITE, &svm->vcpu, ecx, (u32)data, (u32)(data >> 32),
|
||||
handler);
|
||||
|
||||
svm->next_rip = svm->vmcb->save.rip + 2;
|
||||
if (svm_set_msr(&svm->vcpu, ecx, data))
|
||||
kvm_inject_gp(&svm->vcpu, 0);
|
||||
@@ -1323,6 +1366,8 @@ static int msr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
|
||||
static int interrupt_window_interception(struct vcpu_svm *svm,
|
||||
struct kvm_run *kvm_run)
|
||||
{
|
||||
KVMTRACE_0D(PEND_INTR, &svm->vcpu, handler);
|
||||
|
||||
svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VINTR);
|
||||
svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
|
||||
/*
|
||||
@@ -1364,8 +1409,8 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
|
||||
[SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
|
||||
[SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
|
||||
[SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
|
||||
[SVM_EXIT_INTR] = nop_on_interception,
|
||||
[SVM_EXIT_NMI] = nop_on_interception,
|
||||
[SVM_EXIT_INTR] = intr_interception,
|
||||
[SVM_EXIT_NMI] = nmi_interception,
|
||||
[SVM_EXIT_SMI] = nop_on_interception,
|
||||
[SVM_EXIT_INIT] = nop_on_interception,
|
||||
[SVM_EXIT_VINTR] = interrupt_window_interception,
|
||||
@@ -1397,6 +1442,9 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
u32 exit_code = svm->vmcb->control.exit_code;
|
||||
|
||||
KVMTRACE_3D(VMEXIT, vcpu, exit_code, (u32)svm->vmcb->save.rip,
|
||||
(u32)((u64)svm->vmcb->save.rip >> 32), entryexit);
|
||||
|
||||
if (npt_enabled) {
|
||||
int mmu_reload = 0;
|
||||
if ((vcpu->arch.cr0 ^ svm->vmcb->save.cr0) & X86_CR0_PG) {
|
||||
@@ -1470,6 +1518,8 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
|
||||
{
|
||||
struct vmcb_control_area *control;
|
||||
|
||||
KVMTRACE_1D(INJ_VIRQ, &svm->vcpu, (u32)irq, handler);
|
||||
|
||||
control = &svm->vmcb->control;
|
||||
control->int_vector = irq;
|
||||
control->int_ctl &= ~V_INTR_PRIO_MASK;
|
||||
@@ -1660,9 +1710,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
sync_lapic_to_cr8(vcpu);
|
||||
|
||||
save_host_msrs(vcpu);
|
||||
fs_selector = read_fs();
|
||||
gs_selector = read_gs();
|
||||
ldt_selector = read_ldt();
|
||||
fs_selector = kvm_read_fs();
|
||||
gs_selector = kvm_read_gs();
|
||||
ldt_selector = kvm_read_ldt();
|
||||
svm->host_cr2 = kvm_read_cr2();
|
||||
svm->host_dr6 = read_dr6();
|
||||
svm->host_dr7 = read_dr7();
|
||||
@@ -1716,17 +1766,17 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
/* Enter guest mode */
|
||||
"push %%rax \n\t"
|
||||
"mov %c[vmcb](%[svm]), %%rax \n\t"
|
||||
SVM_VMLOAD "\n\t"
|
||||
SVM_VMRUN "\n\t"
|
||||
SVM_VMSAVE "\n\t"
|
||||
__ex(SVM_VMLOAD) "\n\t"
|
||||
__ex(SVM_VMRUN) "\n\t"
|
||||
__ex(SVM_VMSAVE) "\n\t"
|
||||
"pop %%rax \n\t"
|
||||
#else
|
||||
/* Enter guest mode */
|
||||
"push %%eax \n\t"
|
||||
"mov %c[vmcb](%[svm]), %%eax \n\t"
|
||||
SVM_VMLOAD "\n\t"
|
||||
SVM_VMRUN "\n\t"
|
||||
SVM_VMSAVE "\n\t"
|
||||
__ex(SVM_VMLOAD) "\n\t"
|
||||
__ex(SVM_VMRUN) "\n\t"
|
||||
__ex(SVM_VMSAVE) "\n\t"
|
||||
"pop %%eax \n\t"
|
||||
#endif
|
||||
|
||||
@@ -1795,9 +1845,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
write_dr7(svm->host_dr7);
|
||||
kvm_write_cr2(svm->host_cr2);
|
||||
|
||||
load_fs(fs_selector);
|
||||
load_gs(gs_selector);
|
||||
load_ldt(ldt_selector);
|
||||
kvm_load_fs(fs_selector);
|
||||
kvm_load_gs(gs_selector);
|
||||
kvm_load_ldt(ldt_selector);
|
||||
load_host_msrs(vcpu);
|
||||
|
||||
reload_tss(vcpu);
|
||||
@@ -1889,7 +1939,6 @@ static struct kvm_x86_ops svm_x86_ops = {
|
||||
.prepare_guest_switch = svm_prepare_guest_switch,
|
||||
.vcpu_load = svm_vcpu_load,
|
||||
.vcpu_put = svm_vcpu_put,
|
||||
.vcpu_decache = svm_vcpu_decache,
|
||||
|
||||
.set_guest_debug = svm_guest_debug,
|
||||
.get_msr = svm_get_msr,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user