summaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorAvi Kivity2007-10-22 16:50:39 +0200
committerAvi Kivity2008-01-30 17:01:20 +0100
commitb209749f528488c4c0d20a42c0fbcbf49e6933b3 (patch)
tree0e0a24225a5c6bca1c1986cc0daaf8753424cfe6 /arch/x86/kvm/x86.c
parentKVM: Print data for unimplemented wrmsr (diff)
downloadkernel-qcow2-linux-b209749f528488c4c0d20a42c0fbcbf49e6933b3.tar.gz
kernel-qcow2-linux-b209749f528488c4c0d20a42c0fbcbf49e6933b3.tar.xz
kernel-qcow2-linux-b209749f528488c4c0d20a42c0fbcbf49e6933b3.zip
KVM: local APIC TPR access reporting facility
Add a facility to report on accesses to the local apic tpr even if the local apic is emulated in the kernel. This is basically a hack that allows userspace to patch Windows which tends to bang on the tpr a lot. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 513258c797ca..c2b80884447e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -684,6 +684,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_USER_MEMORY:
case KVM_CAP_SET_TSS_ADDR:
case KVM_CAP_EXT_CPUID:
+ case KVM_CAP_VAPIC:
r = 1;
break;
default:
@@ -1055,6 +1056,15 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
return 0;
}
+static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu,
+ struct kvm_tpr_access_ctl *tac)
+{
+ if (tac->flags)
+ return -EINVAL;
+ vcpu->arch.tpr_access_reporting = !!tac->enabled;
+ return 0;
+}
+
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -1148,6 +1158,21 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
case KVM_SET_MSRS:
r = msr_io(vcpu, argp, do_set_msr, 0);
break;
+ case KVM_TPR_ACCESS_REPORTING: {
+ struct kvm_tpr_access_ctl tac;
+
+ r = -EFAULT;
+ if (copy_from_user(&tac, argp, sizeof tac))
+ goto out;
+ r = vcpu_ioctl_tpr_access_reporting(vcpu, &tac);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user(argp, &tac, sizeof tac))
+ goto out;
+ r = 0;
+ break;
+ };
default:
r = -EINVAL;
}