aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
authorEddie Dong <eddie.dong@intel.com>2007-09-12 03:58:04 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:25 -0400
commit97222cc8316328965851ed28d23f6b64b4c912d2 (patch)
tree469b2f72e74046a7aec5061df194c3f68812a224 /drivers/kvm/kvm_main.c
parent7017fc3d1a12e30ea7df4992152978a188433457 (diff)
KVM: Emulate local APIC in kernel
Because lightweight exits (exits which don't involve userspace) are many times faster than heavyweight exits, it makes sense to emulate high usage devices in the kernel. The local APIC is one such device, especially for Windows and for SMP, so we add an APIC model to kvm. It also allows in-kernel host-side drivers to inject interrupts without going through userspace. [compile fix on i386 from Jindrich Makovicka] Signed-off-by: Yaozu (Eddie) Dong <Eddie.Dong@intel.com> Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c52
1 files changed, 42 insertions, 10 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index f879efbefcdf..401e3cdc4607 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -281,6 +281,7 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_init);
281void kvm_vcpu_uninit(struct kvm_vcpu *vcpu) 281void kvm_vcpu_uninit(struct kvm_vcpu *vcpu)
282{ 282{
283 kvm_mmu_destroy(vcpu); 283 kvm_mmu_destroy(vcpu);
284 kvm_free_apic(vcpu->apic);
284 free_page((unsigned long)vcpu->pio_data); 285 free_page((unsigned long)vcpu->pio_data);
285 free_page((unsigned long)vcpu->run); 286 free_page((unsigned long)vcpu->run);
286} 287}
@@ -598,25 +599,38 @@ void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
598 inject_gp(vcpu); 599 inject_gp(vcpu);
599 return; 600 return;
600 } 601 }
601 vcpu->cr8 = cr8; 602 if (irqchip_in_kernel(vcpu->kvm))
603 kvm_lapic_set_tpr(vcpu, cr8);
604 else
605 vcpu->cr8 = cr8;
602} 606}
603EXPORT_SYMBOL_GPL(set_cr8); 607EXPORT_SYMBOL_GPL(set_cr8);
604 608
605unsigned long get_cr8(struct kvm_vcpu *vcpu) 609unsigned long get_cr8(struct kvm_vcpu *vcpu)
606{ 610{
607 return vcpu->cr8; 611 if (irqchip_in_kernel(vcpu->kvm))
612 return kvm_lapic_get_cr8(vcpu);
613 else
614 return vcpu->cr8;
608} 615}
609EXPORT_SYMBOL_GPL(get_cr8); 616EXPORT_SYMBOL_GPL(get_cr8);
610 617
611u64 kvm_get_apic_base(struct kvm_vcpu *vcpu) 618u64 kvm_get_apic_base(struct kvm_vcpu *vcpu)
612{ 619{
613 return vcpu->apic_base; 620 if (irqchip_in_kernel(vcpu->kvm))
621 return vcpu->apic_base;
622 else
623 return vcpu->apic_base;
614} 624}
615EXPORT_SYMBOL_GPL(kvm_get_apic_base); 625EXPORT_SYMBOL_GPL(kvm_get_apic_base);
616 626
617void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data) 627void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data)
618{ 628{
619 vcpu->apic_base = data; 629 /* TODO: reserve bits check */
630 if (irqchip_in_kernel(vcpu->kvm))
631 kvm_lapic_set_base(vcpu, data);
632 else
633 vcpu->apic_base = data;
620} 634}
621EXPORT_SYMBOL_GPL(kvm_set_apic_base); 635EXPORT_SYMBOL_GPL(kvm_set_apic_base);
622 636
@@ -986,15 +1000,31 @@ static int emulator_write_std(unsigned long addr,
986 return X86EMUL_UNHANDLEABLE; 1000 return X86EMUL_UNHANDLEABLE;
987} 1001}
988 1002
1003/*
1004 * Only apic need an MMIO device hook, so shortcut now..
1005 */
1006static struct kvm_io_device *vcpu_find_pervcpu_dev(struct kvm_vcpu *vcpu,
1007 gpa_t addr)
1008{
1009 struct kvm_io_device *dev;
1010
1011 if (vcpu->apic) {
1012 dev = &vcpu->apic->dev;
1013 if (dev->in_range(dev, addr))
1014 return dev;
1015 }
1016 return NULL;
1017}
1018
989static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, 1019static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
990 gpa_t addr) 1020 gpa_t addr)
991{ 1021{
992 /* 1022 struct kvm_io_device *dev;
993 * Note that its important to have this wrapper function because 1023
994 * in the very near future we will be checking for MMIOs against 1024 dev = vcpu_find_pervcpu_dev(vcpu, addr);
995 * the LAPIC as well as the general MMIO bus 1025 if (dev == NULL)
996 */ 1026 dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
997 return kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr); 1027 return dev;
998} 1028}
999 1029
1000static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu, 1030static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,
@@ -2256,6 +2286,8 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
2256{ 2286{
2257 if (irq->irq < 0 || irq->irq >= 256) 2287 if (irq->irq < 0 || irq->irq >= 256)
2258 return -EINVAL; 2288 return -EINVAL;
2289 if (irqchip_in_kernel(vcpu->kvm))
2290 return -ENXIO;
2259 vcpu_load(vcpu); 2291 vcpu_load(vcpu);
2260 2292
2261 set_bit(irq->irq, vcpu->irq_pending); 2293 set_bit(irq->irq, vcpu->irq_pending);