diff options
-rw-r--r-- | arch/x86/kvm/lapic.c | 21 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 25 | ||||
-rw-r--r-- | include/asm-x86/kvm_host.h | 1 | ||||
-rw-r--r-- | include/linux/kvm.h | 17 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 2 |
5 files changed, 65 insertions, 1 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 4076331b01ee..50c3f3a8dd3d 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -551,6 +551,23 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic) | |||
551 | return tmcct; | 551 | return tmcct; |
552 | } | 552 | } |
553 | 553 | ||
554 | static void __report_tpr_access(struct kvm_lapic *apic, bool write) | ||
555 | { | ||
556 | struct kvm_vcpu *vcpu = apic->vcpu; | ||
557 | struct kvm_run *run = vcpu->run; | ||
558 | |||
559 | set_bit(KVM_REQ_REPORT_TPR_ACCESS, &vcpu->requests); | ||
560 | kvm_x86_ops->cache_regs(vcpu); | ||
561 | run->tpr_access.rip = vcpu->arch.rip; | ||
562 | run->tpr_access.is_write = write; | ||
563 | } | ||
564 | |||
565 | static inline void report_tpr_access(struct kvm_lapic *apic, bool write) | ||
566 | { | ||
567 | if (apic->vcpu->arch.tpr_access_reporting) | ||
568 | __report_tpr_access(apic, write); | ||
569 | } | ||
570 | |||
554 | static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset) | 571 | static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset) |
555 | { | 572 | { |
556 | u32 val = 0; | 573 | u32 val = 0; |
@@ -568,6 +585,9 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset) | |||
568 | val = apic_get_tmcct(apic); | 585 | val = apic_get_tmcct(apic); |
569 | break; | 586 | break; |
570 | 587 | ||
588 | case APIC_TASKPRI: | ||
589 | report_tpr_access(apic, false); | ||
590 | /* fall thru */ | ||
571 | default: | 591 | default: |
572 | apic_update_ppr(apic); | 592 | apic_update_ppr(apic); |
573 | val = apic_get_reg(apic, offset); | 593 | val = apic_get_reg(apic, offset); |
@@ -677,6 +697,7 @@ static void apic_mmio_write(struct kvm_io_device *this, | |||
677 | break; | 697 | break; |
678 | 698 | ||
679 | case APIC_TASKPRI: | 699 | case APIC_TASKPRI: |
700 | report_tpr_access(apic, true); | ||
680 | apic_set_tpr(apic, val & 0xff); | 701 | apic_set_tpr(apic, val & 0xff); |
681 | break; | 702 | break; |
682 | 703 | ||
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) | |||
684 | case KVM_CAP_USER_MEMORY: | 684 | case KVM_CAP_USER_MEMORY: |
685 | case KVM_CAP_SET_TSS_ADDR: | 685 | case KVM_CAP_SET_TSS_ADDR: |
686 | case KVM_CAP_EXT_CPUID: | 686 | case KVM_CAP_EXT_CPUID: |
687 | case KVM_CAP_VAPIC: | ||
687 | r = 1; | 688 | r = 1; |
688 | break; | 689 | break; |
689 | default: | 690 | default: |
@@ -1055,6 +1056,15 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, | |||
1055 | return 0; | 1056 | return 0; |
1056 | } | 1057 | } |
1057 | 1058 | ||
1059 | static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu, | ||
1060 | struct kvm_tpr_access_ctl *tac) | ||
1061 | { | ||
1062 | if (tac->flags) | ||
1063 | return -EINVAL; | ||
1064 | vcpu->arch.tpr_access_reporting = !!tac->enabled; | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1058 | long kvm_arch_vcpu_ioctl(struct file *filp, | 1068 | long kvm_arch_vcpu_ioctl(struct file *filp, |
1059 | unsigned int ioctl, unsigned long arg) | 1069 | unsigned int ioctl, unsigned long arg) |
1060 | { | 1070 | { |
@@ -1148,6 +1158,21 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
1148 | case KVM_SET_MSRS: | 1158 | case KVM_SET_MSRS: |
1149 | r = msr_io(vcpu, argp, do_set_msr, 0); | 1159 | r = msr_io(vcpu, argp, do_set_msr, 0); |
1150 | break; | 1160 | break; |
1161 | case KVM_TPR_ACCESS_REPORTING: { | ||
1162 | struct kvm_tpr_access_ctl tac; | ||
1163 | |||
1164 | r = -EFAULT; | ||
1165 | if (copy_from_user(&tac, argp, sizeof tac)) | ||
1166 | goto out; | ||
1167 | r = vcpu_ioctl_tpr_access_reporting(vcpu, &tac); | ||
1168 | if (r) | ||
1169 | goto out; | ||
1170 | r = -EFAULT; | ||
1171 | if (copy_to_user(argp, &tac, sizeof tac)) | ||
1172 | goto out; | ||
1173 | r = 0; | ||
1174 | break; | ||
1175 | }; | ||
1151 | default: | 1176 | default: |
1152 | r = -EINVAL; | 1177 | r = -EINVAL; |
1153 | } | 1178 | } |
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index ced1bebabbc8..6e649af08d19 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h | |||
@@ -211,6 +211,7 @@ struct kvm_vcpu_arch { | |||
211 | int mp_state; | 211 | int mp_state; |
212 | int sipi_vector; | 212 | int sipi_vector; |
213 | u64 ia32_misc_enable_msr; | 213 | u64 ia32_misc_enable_msr; |
214 | bool tpr_access_reporting; | ||
214 | 215 | ||
215 | struct kvm_mmu mmu; | 216 | struct kvm_mmu mmu; |
216 | 217 | ||
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index de9f28d96ced..850f5ef76636 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -72,6 +72,7 @@ struct kvm_irqchip { | |||
72 | #define KVM_EXIT_FAIL_ENTRY 9 | 72 | #define KVM_EXIT_FAIL_ENTRY 9 |
73 | #define KVM_EXIT_INTR 10 | 73 | #define KVM_EXIT_INTR 10 |
74 | #define KVM_EXIT_SET_TPR 11 | 74 | #define KVM_EXIT_SET_TPR 11 |
75 | #define KVM_EXIT_TPR_ACCESS 12 | ||
75 | 76 | ||
76 | /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ | 77 | /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ |
77 | struct kvm_run { | 78 | struct kvm_run { |
@@ -130,6 +131,12 @@ struct kvm_run { | |||
130 | __u32 longmode; | 131 | __u32 longmode; |
131 | __u32 pad; | 132 | __u32 pad; |
132 | } hypercall; | 133 | } hypercall; |
134 | /* KVM_EXIT_TPR_ACCESS */ | ||
135 | struct { | ||
136 | __u64 rip; | ||
137 | __u32 is_write; | ||
138 | __u32 pad; | ||
139 | } tpr_access; | ||
133 | /* Fix the size of the union. */ | 140 | /* Fix the size of the union. */ |
134 | char padding[256]; | 141 | char padding[256]; |
135 | }; | 142 | }; |
@@ -202,6 +209,13 @@ struct kvm_signal_mask { | |||
202 | __u8 sigset[0]; | 209 | __u8 sigset[0]; |
203 | }; | 210 | }; |
204 | 211 | ||
212 | /* for KVM_TPR_ACCESS_REPORTING */ | ||
213 | struct kvm_tpr_access_ctl { | ||
214 | __u32 enabled; | ||
215 | __u32 flags; | ||
216 | __u32 reserved[8]; | ||
217 | }; | ||
218 | |||
205 | #define KVMIO 0xAE | 219 | #define KVMIO 0xAE |
206 | 220 | ||
207 | /* | 221 | /* |
@@ -229,6 +243,7 @@ struct kvm_signal_mask { | |||
229 | #define KVM_CAP_USER_MEMORY 3 | 243 | #define KVM_CAP_USER_MEMORY 3 |
230 | #define KVM_CAP_SET_TSS_ADDR 4 | 244 | #define KVM_CAP_SET_TSS_ADDR 4 |
231 | #define KVM_CAP_EXT_CPUID 5 | 245 | #define KVM_CAP_EXT_CPUID 5 |
246 | #define KVM_CAP_VAPIC 6 | ||
232 | 247 | ||
233 | /* | 248 | /* |
234 | * ioctls for VM fds | 249 | * ioctls for VM fds |
@@ -274,5 +289,7 @@ struct kvm_signal_mask { | |||
274 | #define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state) | 289 | #define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state) |
275 | #define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2) | 290 | #define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2) |
276 | #define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2) | 291 | #define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2) |
292 | /* Available with KVM_CAP_VAPIC */ | ||
293 | #define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl) | ||
277 | 294 | ||
278 | #endif | 295 | #endif |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 953b50aa0e61..9ff5904c5072 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -35,7 +35,7 @@ | |||
35 | * vcpu->requests bit members | 35 | * vcpu->requests bit members |
36 | */ | 36 | */ |
37 | #define KVM_REQ_TLB_FLUSH 0 | 37 | #define KVM_REQ_TLB_FLUSH 0 |
38 | 38 | #define KVM_REQ_REPORT_TPR_ACCESS 2 | |
39 | 39 | ||
40 | struct kvm_vcpu; | 40 | struct kvm_vcpu; |
41 | extern struct kmem_cache *kvm_vcpu_cache; | 41 | extern struct kmem_cache *kvm_vcpu_cache; |