diff options
| -rw-r--r-- | drivers/kvm/kvm.h | 35 | ||||
| -rw-r--r-- | drivers/kvm/kvm_main.c | 61 | ||||
| -rw-r--r-- | drivers/kvm/mmu.c | 2 | ||||
| -rw-r--r-- | drivers/kvm/paging_tmpl.h | 2 | ||||
| -rw-r--r-- | drivers/kvm/svm.c | 14 | ||||
| -rw-r--r-- | drivers/kvm/vmx.c | 18 |
6 files changed, 79 insertions, 53 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index b9c318a9e334..d1a90c5d76ce 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
| @@ -236,6 +236,22 @@ struct kvm_pio_request { | |||
| 236 | int rep; | 236 | int rep; |
| 237 | }; | 237 | }; |
| 238 | 238 | ||
| 239 | struct kvm_stat { | ||
| 240 | u32 pf_fixed; | ||
| 241 | u32 pf_guest; | ||
| 242 | u32 tlb_flush; | ||
| 243 | u32 invlpg; | ||
| 244 | |||
| 245 | u32 exits; | ||
| 246 | u32 io_exits; | ||
| 247 | u32 mmio_exits; | ||
| 248 | u32 signal_exits; | ||
| 249 | u32 irq_window_exits; | ||
| 250 | u32 halt_exits; | ||
| 251 | u32 request_irq_exits; | ||
| 252 | u32 irq_exits; | ||
| 253 | }; | ||
| 254 | |||
| 239 | struct kvm_vcpu { | 255 | struct kvm_vcpu { |
| 240 | struct kvm *kvm; | 256 | struct kvm *kvm; |
| 241 | union { | 257 | union { |
| @@ -298,6 +314,8 @@ struct kvm_vcpu { | |||
| 298 | int sigset_active; | 314 | int sigset_active; |
| 299 | sigset_t sigset; | 315 | sigset_t sigset; |
| 300 | 316 | ||
| 317 | struct kvm_stat stat; | ||
| 318 | |||
| 301 | struct { | 319 | struct { |
| 302 | int active; | 320 | int active; |
| 303 | u8 save_iopl; | 321 | u8 save_iopl; |
| @@ -347,22 +365,6 @@ struct kvm { | |||
| 347 | struct file *filp; | 365 | struct file *filp; |
| 348 | }; | 366 | }; |
| 349 | 367 | ||
| 350 | struct kvm_stat { | ||
| 351 | u32 pf_fixed; | ||
| 352 | u32 pf_guest; | ||
| 353 | u32 tlb_flush; | ||
| 354 | u32 invlpg; | ||
| 355 | |||
| 356 | u32 exits; | ||
| 357 | u32 io_exits; | ||
| 358 | u32 mmio_exits; | ||
| 359 | u32 signal_exits; | ||
| 360 | u32 irq_window_exits; | ||
| 361 | u32 halt_exits; | ||
| 362 | u32 request_irq_exits; | ||
| 363 | u32 irq_exits; | ||
| 364 | }; | ||
| 365 | |||
| 366 | struct descriptor_table { | 368 | struct descriptor_table { |
| 367 | u16 limit; | 369 | u16 limit; |
| 368 | unsigned long base; | 370 | unsigned long base; |
| @@ -424,7 +426,6 @@ struct kvm_arch_ops { | |||
| 424 | unsigned char *hypercall_addr); | 426 | unsigned char *hypercall_addr); |
| 425 | }; | 427 | }; |
| 426 | 428 | ||
| 427 | extern struct kvm_stat kvm_stat; | ||
| 428 | extern struct kvm_arch_ops *kvm_arch_ops; | 429 | extern struct kvm_arch_ops *kvm_arch_ops; |
| 429 | 430 | ||
| 430 | #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) | 431 | #define kvm_printf(kvm, fmt ...) printk(KERN_DEBUG fmt) |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index f5356358acff..911c8175cc08 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
| @@ -51,27 +51,27 @@ static DEFINE_SPINLOCK(kvm_lock); | |||
| 51 | static LIST_HEAD(vm_list); | 51 | static LIST_HEAD(vm_list); |
| 52 | 52 | ||
| 53 | struct kvm_arch_ops *kvm_arch_ops; | 53 | struct kvm_arch_ops *kvm_arch_ops; |
| 54 | struct kvm_stat kvm_stat; | 54 | |
| 55 | EXPORT_SYMBOL_GPL(kvm_stat); | 55 | #define STAT_OFFSET(x) offsetof(struct kvm_vcpu, stat.x) |
| 56 | 56 | ||
| 57 | static struct kvm_stats_debugfs_item { | 57 | static struct kvm_stats_debugfs_item { |
| 58 | const char *name; | 58 | const char *name; |
| 59 | u32 *data; | 59 | int offset; |
| 60 | struct dentry *dentry; | 60 | struct dentry *dentry; |
| 61 | } debugfs_entries[] = { | 61 | } debugfs_entries[] = { |
| 62 | { "pf_fixed", &kvm_stat.pf_fixed }, | 62 | { "pf_fixed", STAT_OFFSET(pf_fixed) }, |
| 63 | { "pf_guest", &kvm_stat.pf_guest }, | 63 | { "pf_guest", STAT_OFFSET(pf_guest) }, |
| 64 | { "tlb_flush", &kvm_stat.tlb_flush }, | 64 | { "tlb_flush", STAT_OFFSET(tlb_flush) }, |
| 65 | { "invlpg", &kvm_stat.invlpg }, | 65 | { "invlpg", STAT_OFFSET(invlpg) }, |
| 66 | { "exits", &kvm_stat.exits }, | 66 | { "exits", STAT_OFFSET(exits) }, |
| 67 | { "io_exits", &kvm_stat.io_exits }, | 67 | { "io_exits", STAT_OFFSET(io_exits) }, |
| 68 | { "mmio_exits", &kvm_stat.mmio_exits }, | 68 | { "mmio_exits", STAT_OFFSET(mmio_exits) }, |
| 69 | { "signal_exits", &kvm_stat.signal_exits }, | 69 | { "signal_exits", STAT_OFFSET(signal_exits) }, |
| 70 | { "irq_window", &kvm_stat.irq_window_exits }, | 70 | { "irq_window", STAT_OFFSET(irq_window_exits) }, |
| 71 | { "halt_exits", &kvm_stat.halt_exits }, | 71 | { "halt_exits", STAT_OFFSET(halt_exits) }, |
| 72 | { "request_irq", &kvm_stat.request_irq_exits }, | 72 | { "request_irq", STAT_OFFSET(request_irq_exits) }, |
| 73 | { "irq_exits", &kvm_stat.irq_exits }, | 73 | { "irq_exits", STAT_OFFSET(irq_exits) }, |
| 74 | { NULL, NULL } | 74 | { NULL } |
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | static struct dentry *debugfs_dir; | 77 | static struct dentry *debugfs_dir; |
| @@ -2930,14 +2930,39 @@ static struct notifier_block kvm_cpu_notifier = { | |||
| 2930 | .priority = 20, /* must be > scheduler priority */ | 2930 | .priority = 20, /* must be > scheduler priority */ |
| 2931 | }; | 2931 | }; |
| 2932 | 2932 | ||
| 2933 | static u64 stat_get(void *_offset) | ||
| 2934 | { | ||
| 2935 | unsigned offset = (long)_offset; | ||
| 2936 | u64 total = 0; | ||
| 2937 | struct kvm *kvm; | ||
| 2938 | struct kvm_vcpu *vcpu; | ||
| 2939 | int i; | ||
| 2940 | |||
| 2941 | spin_lock(&kvm_lock); | ||
| 2942 | list_for_each_entry(kvm, &vm_list, vm_list) | ||
| 2943 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
| 2944 | vcpu = &kvm->vcpus[i]; | ||
| 2945 | total += *(u32 *)((void *)vcpu + offset); | ||
| 2946 | } | ||
| 2947 | spin_unlock(&kvm_lock); | ||
| 2948 | return total; | ||
| 2949 | } | ||
| 2950 | |||
| 2951 | static void stat_set(void *offset, u64 val) | ||
| 2952 | { | ||
| 2953 | } | ||
| 2954 | |||
| 2955 | DEFINE_SIMPLE_ATTRIBUTE(stat_fops, stat_get, stat_set, "%llu\n"); | ||
| 2956 | |||
| 2933 | static __init void kvm_init_debug(void) | 2957 | static __init void kvm_init_debug(void) |
| 2934 | { | 2958 | { |
| 2935 | struct kvm_stats_debugfs_item *p; | 2959 | struct kvm_stats_debugfs_item *p; |
| 2936 | 2960 | ||
| 2937 | debugfs_dir = debugfs_create_dir("kvm", NULL); | 2961 | debugfs_dir = debugfs_create_dir("kvm", NULL); |
| 2938 | for (p = debugfs_entries; p->name; ++p) | 2962 | for (p = debugfs_entries; p->name; ++p) |
| 2939 | p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir, | 2963 | p->dentry = debugfs_create_file(p->name, 0444, debugfs_dir, |
| 2940 | p->data); | 2964 | (void *)(long)p->offset, |
| 2965 | &stat_fops); | ||
| 2941 | } | 2966 | } |
| 2942 | 2967 | ||
| 2943 | static void kvm_exit_debug(void) | 2968 | static void kvm_exit_debug(void) |
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index 8ccf84e3fda8..32c64f682081 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
| @@ -936,7 +936,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu) | |||
| 936 | 936 | ||
| 937 | static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu) | 937 | static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu) |
| 938 | { | 938 | { |
| 939 | ++kvm_stat.tlb_flush; | 939 | ++vcpu->stat.tlb_flush; |
| 940 | kvm_arch_ops->tlb_flush(vcpu); | 940 | kvm_arch_ops->tlb_flush(vcpu); |
| 941 | } | 941 | } |
| 942 | 942 | ||
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h index b94010dad809..73ffbffb1097 100644 --- a/drivers/kvm/paging_tmpl.h +++ b/drivers/kvm/paging_tmpl.h | |||
| @@ -448,7 +448,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, | |||
| 448 | if (is_io_pte(*shadow_pte)) | 448 | if (is_io_pte(*shadow_pte)) |
| 449 | return 1; | 449 | return 1; |
| 450 | 450 | ||
| 451 | ++kvm_stat.pf_fixed; | 451 | ++vcpu->stat.pf_fixed; |
| 452 | kvm_mmu_audit(vcpu, "post page fault (fixed)"); | 452 | kvm_mmu_audit(vcpu, "post page fault (fixed)"); |
| 453 | 453 | ||
| 454 | return write_pt; | 454 | return write_pt; |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 61ed7352e506..644efc5381ad 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
| @@ -914,7 +914,7 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 914 | case EMULATE_DONE: | 914 | case EMULATE_DONE: |
| 915 | return 1; | 915 | return 1; |
| 916 | case EMULATE_DO_MMIO: | 916 | case EMULATE_DO_MMIO: |
| 917 | ++kvm_stat.mmio_exits; | 917 | ++vcpu->stat.mmio_exits; |
| 918 | kvm_run->exit_reason = KVM_EXIT_MMIO; | 918 | kvm_run->exit_reason = KVM_EXIT_MMIO; |
| 919 | return 0; | 919 | return 0; |
| 920 | case EMULATE_FAIL: | 920 | case EMULATE_FAIL: |
| @@ -1054,7 +1054,7 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 1054 | unsigned long count; | 1054 | unsigned long count; |
| 1055 | gva_t address = 0; | 1055 | gva_t address = 0; |
| 1056 | 1056 | ||
| 1057 | ++kvm_stat.io_exits; | 1057 | ++vcpu->stat.io_exits; |
| 1058 | 1058 | ||
| 1059 | vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2; | 1059 | vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2; |
| 1060 | 1060 | ||
| @@ -1096,7 +1096,7 @@ static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 1096 | return 1; | 1096 | return 1; |
| 1097 | 1097 | ||
| 1098 | kvm_run->exit_reason = KVM_EXIT_HLT; | 1098 | kvm_run->exit_reason = KVM_EXIT_HLT; |
| 1099 | ++kvm_stat.halt_exits; | 1099 | ++vcpu->stat.halt_exits; |
| 1100 | return 0; | 1100 | return 0; |
| 1101 | } | 1101 | } |
| 1102 | 1102 | ||
| @@ -1264,7 +1264,7 @@ static int interrupt_window_interception(struct kvm_vcpu *vcpu, | |||
| 1264 | */ | 1264 | */ |
| 1265 | if (kvm_run->request_interrupt_window && | 1265 | if (kvm_run->request_interrupt_window && |
| 1266 | !vcpu->irq_summary) { | 1266 | !vcpu->irq_summary) { |
| 1267 | ++kvm_stat.irq_window_exits; | 1267 | ++vcpu->stat.irq_window_exits; |
| 1268 | kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; | 1268 | kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; |
| 1269 | return 0; | 1269 | return 0; |
| 1270 | } | 1270 | } |
| @@ -1636,14 +1636,14 @@ again: | |||
| 1636 | r = handle_exit(vcpu, kvm_run); | 1636 | r = handle_exit(vcpu, kvm_run); |
| 1637 | if (r > 0) { | 1637 | if (r > 0) { |
| 1638 | if (signal_pending(current)) { | 1638 | if (signal_pending(current)) { |
| 1639 | ++kvm_stat.signal_exits; | 1639 | ++vcpu->stat.signal_exits; |
| 1640 | post_kvm_run_save(vcpu, kvm_run); | 1640 | post_kvm_run_save(vcpu, kvm_run); |
| 1641 | kvm_run->exit_reason = KVM_EXIT_INTR; | 1641 | kvm_run->exit_reason = KVM_EXIT_INTR; |
| 1642 | return -EINTR; | 1642 | return -EINTR; |
| 1643 | } | 1643 | } |
| 1644 | 1644 | ||
| 1645 | if (dm_request_for_irq_injection(vcpu, kvm_run)) { | 1645 | if (dm_request_for_irq_injection(vcpu, kvm_run)) { |
| 1646 | ++kvm_stat.request_irq_exits; | 1646 | ++vcpu->stat.request_irq_exits; |
| 1647 | post_kvm_run_save(vcpu, kvm_run); | 1647 | post_kvm_run_save(vcpu, kvm_run); |
| 1648 | kvm_run->exit_reason = KVM_EXIT_INTR; | 1648 | kvm_run->exit_reason = KVM_EXIT_INTR; |
| 1649 | return -EINTR; | 1649 | return -EINTR; |
| @@ -1672,7 +1672,7 @@ static void svm_inject_page_fault(struct kvm_vcpu *vcpu, | |||
| 1672 | { | 1672 | { |
| 1673 | uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info; | 1673 | uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info; |
| 1674 | 1674 | ||
| 1675 | ++kvm_stat.pf_guest; | 1675 | ++vcpu->stat.pf_guest; |
| 1676 | 1676 | ||
| 1677 | if (is_page_fault(exit_int_info)) { | 1677 | if (is_page_fault(exit_int_info)) { |
| 1678 | 1678 | ||
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 37537af126d1..10845b7ff297 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
| @@ -1396,7 +1396,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 1396 | case EMULATE_DONE: | 1396 | case EMULATE_DONE: |
| 1397 | return 1; | 1397 | return 1; |
| 1398 | case EMULATE_DO_MMIO: | 1398 | case EMULATE_DO_MMIO: |
| 1399 | ++kvm_stat.mmio_exits; | 1399 | ++vcpu->stat.mmio_exits; |
| 1400 | kvm_run->exit_reason = KVM_EXIT_MMIO; | 1400 | kvm_run->exit_reason = KVM_EXIT_MMIO; |
| 1401 | return 0; | 1401 | return 0; |
| 1402 | case EMULATE_FAIL: | 1402 | case EMULATE_FAIL: |
| @@ -1425,7 +1425,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 1425 | static int handle_external_interrupt(struct kvm_vcpu *vcpu, | 1425 | static int handle_external_interrupt(struct kvm_vcpu *vcpu, |
| 1426 | struct kvm_run *kvm_run) | 1426 | struct kvm_run *kvm_run) |
| 1427 | { | 1427 | { |
| 1428 | ++kvm_stat.irq_exits; | 1428 | ++vcpu->stat.irq_exits; |
| 1429 | return 1; | 1429 | return 1; |
| 1430 | } | 1430 | } |
| 1431 | 1431 | ||
| @@ -1492,7 +1492,7 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 1492 | unsigned long count; | 1492 | unsigned long count; |
| 1493 | gva_t address; | 1493 | gva_t address; |
| 1494 | 1494 | ||
| 1495 | ++kvm_stat.io_exits; | 1495 | ++vcpu->stat.io_exits; |
| 1496 | exit_qualification = vmcs_read64(EXIT_QUALIFICATION); | 1496 | exit_qualification = vmcs_read64(EXIT_QUALIFICATION); |
| 1497 | in = (exit_qualification & 8) != 0; | 1497 | in = (exit_qualification & 8) != 0; |
| 1498 | size = (exit_qualification & 7) + 1; | 1498 | size = (exit_qualification & 7) + 1; |
| @@ -1682,7 +1682,7 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu, | |||
| 1682 | if (kvm_run->request_interrupt_window && | 1682 | if (kvm_run->request_interrupt_window && |
| 1683 | !vcpu->irq_summary) { | 1683 | !vcpu->irq_summary) { |
| 1684 | kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; | 1684 | kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; |
| 1685 | ++kvm_stat.irq_window_exits; | 1685 | ++vcpu->stat.irq_window_exits; |
| 1686 | return 0; | 1686 | return 0; |
| 1687 | } | 1687 | } |
| 1688 | return 1; | 1688 | return 1; |
| @@ -1695,7 +1695,7 @@ static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 1695 | return 1; | 1695 | return 1; |
| 1696 | 1696 | ||
| 1697 | kvm_run->exit_reason = KVM_EXIT_HLT; | 1697 | kvm_run->exit_reason = KVM_EXIT_HLT; |
| 1698 | ++kvm_stat.halt_exits; | 1698 | ++vcpu->stat.halt_exits; |
| 1699 | return 0; | 1699 | return 0; |
| 1700 | } | 1700 | } |
| 1701 | 1701 | ||
| @@ -1956,7 +1956,7 @@ again: | |||
| 1956 | 1956 | ||
| 1957 | reload_tss(); | 1957 | reload_tss(); |
| 1958 | } | 1958 | } |
| 1959 | ++kvm_stat.exits; | 1959 | ++vcpu->stat.exits; |
| 1960 | 1960 | ||
| 1961 | #ifdef CONFIG_X86_64 | 1961 | #ifdef CONFIG_X86_64 |
| 1962 | if (is_long_mode(vcpu)) { | 1962 | if (is_long_mode(vcpu)) { |
| @@ -1988,14 +1988,14 @@ again: | |||
| 1988 | if (r > 0) { | 1988 | if (r > 0) { |
| 1989 | /* Give scheduler a change to reschedule. */ | 1989 | /* Give scheduler a change to reschedule. */ |
| 1990 | if (signal_pending(current)) { | 1990 | if (signal_pending(current)) { |
| 1991 | ++kvm_stat.signal_exits; | 1991 | ++vcpu->stat.signal_exits; |
| 1992 | post_kvm_run_save(vcpu, kvm_run); | 1992 | post_kvm_run_save(vcpu, kvm_run); |
| 1993 | kvm_run->exit_reason = KVM_EXIT_INTR; | 1993 | kvm_run->exit_reason = KVM_EXIT_INTR; |
| 1994 | return -EINTR; | 1994 | return -EINTR; |
| 1995 | } | 1995 | } |
| 1996 | 1996 | ||
| 1997 | if (dm_request_for_irq_injection(vcpu, kvm_run)) { | 1997 | if (dm_request_for_irq_injection(vcpu, kvm_run)) { |
| 1998 | ++kvm_stat.request_irq_exits; | 1998 | ++vcpu->stat.request_irq_exits; |
| 1999 | post_kvm_run_save(vcpu, kvm_run); | 1999 | post_kvm_run_save(vcpu, kvm_run); |
| 2000 | kvm_run->exit_reason = KVM_EXIT_INTR; | 2000 | kvm_run->exit_reason = KVM_EXIT_INTR; |
| 2001 | return -EINTR; | 2001 | return -EINTR; |
| @@ -2021,7 +2021,7 @@ static void vmx_inject_page_fault(struct kvm_vcpu *vcpu, | |||
| 2021 | { | 2021 | { |
| 2022 | u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); | 2022 | u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD); |
| 2023 | 2023 | ||
| 2024 | ++kvm_stat.pf_guest; | 2024 | ++vcpu->stat.pf_guest; |
| 2025 | 2025 | ||
| 2026 | if (is_page_fault(vect_info)) { | 2026 | if (is_page_fault(vect_info)) { |
| 2027 | printk(KERN_DEBUG "inject_page_fault: " | 2027 | printk(KERN_DEBUG "inject_page_fault: " |
