diff options
| -rw-r--r-- | arch/arm/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/mips/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/mips/kvm/mips.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/kvm/booke.c | 1 | ||||
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 1 | ||||
| -rw-r--r-- | include/trace/events/kvm.h | 19 | ||||
| -rw-r--r-- | virt/kvm/kvm_main.c | 48 |
13 files changed, 71 insertions, 7 deletions
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index bde494654bcc..6a79314bc1df 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h | |||
| @@ -148,6 +148,7 @@ struct kvm_vm_stat { | |||
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | struct kvm_vcpu_stat { | 150 | struct kvm_vcpu_stat { |
| 151 | u32 halt_successful_poll; | ||
| 151 | u32 halt_wakeup; | 152 | u32 halt_wakeup; |
| 152 | }; | 153 | }; |
| 153 | 154 | ||
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2c49aa4ac818..8efde89613f2 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h | |||
| @@ -165,6 +165,7 @@ struct kvm_vm_stat { | |||
| 165 | }; | 165 | }; |
| 166 | 166 | ||
| 167 | struct kvm_vcpu_stat { | 167 | struct kvm_vcpu_stat { |
| 168 | u32 halt_successful_poll; | ||
| 168 | u32 halt_wakeup; | 169 | u32 halt_wakeup; |
| 169 | }; | 170 | }; |
| 170 | 171 | ||
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index f2c249796ea8..ac4fc716062b 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h | |||
| @@ -120,6 +120,7 @@ struct kvm_vcpu_stat { | |||
| 120 | u32 resvd_inst_exits; | 120 | u32 resvd_inst_exits; |
| 121 | u32 break_inst_exits; | 121 | u32 break_inst_exits; |
| 122 | u32 flush_dcache_exits; | 122 | u32 flush_dcache_exits; |
| 123 | u32 halt_successful_poll; | ||
| 123 | u32 halt_wakeup; | 124 | u32 halt_wakeup; |
| 124 | }; | 125 | }; |
| 125 | 126 | ||
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index e97b90784031..c9eccf5df912 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c | |||
| @@ -49,6 +49,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 49 | { "resvd_inst", VCPU_STAT(resvd_inst_exits), KVM_STAT_VCPU }, | 49 | { "resvd_inst", VCPU_STAT(resvd_inst_exits), KVM_STAT_VCPU }, |
| 50 | { "break_inst", VCPU_STAT(break_inst_exits), KVM_STAT_VCPU }, | 50 | { "break_inst", VCPU_STAT(break_inst_exits), KVM_STAT_VCPU }, |
| 51 | { "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU }, | 51 | { "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU }, |
| 52 | { "halt_successful_poll", VCPU_STAT(halt_successful_poll), KVM_STAT_VCPU }, | ||
| 52 | { "halt_wakeup", VCPU_STAT(halt_wakeup), KVM_STAT_VCPU }, | 53 | { "halt_wakeup", VCPU_STAT(halt_wakeup), KVM_STAT_VCPU }, |
| 53 | {NULL} | 54 | {NULL} |
| 54 | }; | 55 | }; |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 7efd666a3fa7..8ef05121d3cd 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
| @@ -107,6 +107,7 @@ struct kvm_vcpu_stat { | |||
| 107 | u32 emulated_inst_exits; | 107 | u32 emulated_inst_exits; |
| 108 | u32 dec_exits; | 108 | u32 dec_exits; |
| 109 | u32 ext_intr_exits; | 109 | u32 ext_intr_exits; |
| 110 | u32 halt_successful_poll; | ||
| 110 | u32 halt_wakeup; | 111 | u32 halt_wakeup; |
| 111 | u32 dbell_exits; | 112 | u32 dbell_exits; |
| 112 | u32 gdbell_exits; | 113 | u32 gdbell_exits; |
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 888bf466d8c6..cfbcdc654201 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
| @@ -52,6 +52,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 52 | { "dec", VCPU_STAT(dec_exits) }, | 52 | { "dec", VCPU_STAT(dec_exits) }, |
| 53 | { "ext_intr", VCPU_STAT(ext_intr_exits) }, | 53 | { "ext_intr", VCPU_STAT(ext_intr_exits) }, |
| 54 | { "queue_intr", VCPU_STAT(queue_intr) }, | 54 | { "queue_intr", VCPU_STAT(queue_intr) }, |
| 55 | { "halt_successful_poll", VCPU_STAT(halt_successful_poll), }, | ||
| 55 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, | 56 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, |
| 56 | { "pf_storage", VCPU_STAT(pf_storage) }, | 57 | { "pf_storage", VCPU_STAT(pf_storage) }, |
| 57 | { "sp_storage", VCPU_STAT(sp_storage) }, | 58 | { "sp_storage", VCPU_STAT(sp_storage) }, |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 9b55dec2d6cc..6c1316a15a27 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
| @@ -62,6 +62,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 62 | { "inst_emu", VCPU_STAT(emulated_inst_exits) }, | 62 | { "inst_emu", VCPU_STAT(emulated_inst_exits) }, |
| 63 | { "dec", VCPU_STAT(dec_exits) }, | 63 | { "dec", VCPU_STAT(dec_exits) }, |
| 64 | { "ext_intr", VCPU_STAT(ext_intr_exits) }, | 64 | { "ext_intr", VCPU_STAT(ext_intr_exits) }, |
| 65 | { "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, | ||
| 65 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, | 66 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, |
| 66 | { "doorbell", VCPU_STAT(dbell_exits) }, | 67 | { "doorbell", VCPU_STAT(dbell_exits) }, |
| 67 | { "guest doorbell", VCPU_STAT(gdbell_exits) }, | 68 | { "guest doorbell", VCPU_STAT(gdbell_exits) }, |
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index d1ecc7fd0579..f79058e3fd98 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
| @@ -196,6 +196,7 @@ struct kvm_vcpu_stat { | |||
| 196 | u32 exit_stop_request; | 196 | u32 exit_stop_request; |
| 197 | u32 exit_validity; | 197 | u32 exit_validity; |
| 198 | u32 exit_instruction; | 198 | u32 exit_instruction; |
| 199 | u32 halt_successful_poll; | ||
| 199 | u32 halt_wakeup; | 200 | u32 halt_wakeup; |
| 200 | u32 instruction_lctl; | 201 | u32 instruction_lctl; |
| 201 | u32 instruction_lctlg; | 202 | u32 instruction_lctlg; |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index b2371c0fd1f8..1dbab2340a66 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
| @@ -51,6 +51,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 51 | { "exit_instruction", VCPU_STAT(exit_instruction) }, | 51 | { "exit_instruction", VCPU_STAT(exit_instruction) }, |
| 52 | { "exit_program_interruption", VCPU_STAT(exit_program_interruption) }, | 52 | { "exit_program_interruption", VCPU_STAT(exit_program_interruption) }, |
| 53 | { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) }, | 53 | { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) }, |
| 54 | { "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, | ||
| 54 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, | 55 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, |
| 55 | { "instruction_lctlg", VCPU_STAT(instruction_lctlg) }, | 56 | { "instruction_lctlg", VCPU_STAT(instruction_lctlg) }, |
| 56 | { "instruction_lctl", VCPU_STAT(instruction_lctl) }, | 57 | { "instruction_lctl", VCPU_STAT(instruction_lctl) }, |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 848947ac6ade..a236e39cc385 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
| @@ -655,6 +655,7 @@ struct kvm_vcpu_stat { | |||
| 655 | u32 irq_window_exits; | 655 | u32 irq_window_exits; |
| 656 | u32 nmi_window_exits; | 656 | u32 nmi_window_exits; |
| 657 | u32 halt_exits; | 657 | u32 halt_exits; |
| 658 | u32 halt_successful_poll; | ||
| 658 | u32 halt_wakeup; | 659 | u32 halt_wakeup; |
| 659 | u32 request_irq_exits; | 660 | u32 request_irq_exits; |
| 660 | u32 irq_exits; | 661 | u32 irq_exits; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1373e04e1f19..bd7a70be41b3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -145,6 +145,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 145 | { "irq_window", VCPU_STAT(irq_window_exits) }, | 145 | { "irq_window", VCPU_STAT(irq_window_exits) }, |
| 146 | { "nmi_window", VCPU_STAT(nmi_window_exits) }, | 146 | { "nmi_window", VCPU_STAT(nmi_window_exits) }, |
| 147 | { "halt_exits", VCPU_STAT(halt_exits) }, | 147 | { "halt_exits", VCPU_STAT(halt_exits) }, |
| 148 | { "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, | ||
| 148 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, | 149 | { "halt_wakeup", VCPU_STAT(halt_wakeup) }, |
| 149 | { "hypercalls", VCPU_STAT(hypercalls) }, | 150 | { "hypercalls", VCPU_STAT(hypercalls) }, |
| 150 | { "request_irq", VCPU_STAT(request_irq_exits) }, | 151 | { "request_irq", VCPU_STAT(request_irq_exits) }, |
diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h index 6edf1f2028cd..6bfe7eec1c2c 100644 --- a/include/trace/events/kvm.h +++ b/include/trace/events/kvm.h | |||
| @@ -37,6 +37,25 @@ TRACE_EVENT(kvm_userspace_exit, | |||
| 37 | __entry->errno < 0 ? -__entry->errno : __entry->reason) | 37 | __entry->errno < 0 ? -__entry->errno : __entry->reason) |
| 38 | ); | 38 | ); |
| 39 | 39 | ||
| 40 | TRACE_EVENT(kvm_vcpu_wakeup, | ||
| 41 | TP_PROTO(__u64 ns, bool waited), | ||
| 42 | TP_ARGS(ns, waited), | ||
| 43 | |||
| 44 | TP_STRUCT__entry( | ||
| 45 | __field( __u64, ns ) | ||
| 46 | __field( bool, waited ) | ||
| 47 | ), | ||
| 48 | |||
| 49 | TP_fast_assign( | ||
| 50 | __entry->ns = ns; | ||
| 51 | __entry->waited = waited; | ||
| 52 | ), | ||
| 53 | |||
| 54 | TP_printk("%s time %lld ns", | ||
| 55 | __entry->waited ? "wait" : "poll", | ||
| 56 | __entry->ns) | ||
| 57 | ); | ||
| 58 | |||
| 40 | #if defined(CONFIG_HAVE_KVM_IRQFD) | 59 | #if defined(CONFIG_HAVE_KVM_IRQFD) |
| 41 | TRACE_EVENT(kvm_set_irq, | 60 | TRACE_EVENT(kvm_set_irq, |
| 42 | TP_PROTO(unsigned int gsi, int level, int irq_source_id), | 61 | TP_PROTO(unsigned int gsi, int level, int irq_source_id), |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 0c281760a1c5..32449e0e9aa8 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -66,6 +66,9 @@ | |||
| 66 | MODULE_AUTHOR("Qumranet"); | 66 | MODULE_AUTHOR("Qumranet"); |
| 67 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
| 68 | 68 | ||
| 69 | unsigned int halt_poll_ns = 0; | ||
| 70 | module_param(halt_poll_ns, uint, S_IRUGO | S_IWUSR); | ||
| 71 | |||
| 69 | /* | 72 | /* |
| 70 | * Ordering of locks: | 73 | * Ordering of locks: |
| 71 | * | 74 | * |
| @@ -1813,29 +1816,60 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn) | |||
| 1813 | } | 1816 | } |
| 1814 | EXPORT_SYMBOL_GPL(mark_page_dirty); | 1817 | EXPORT_SYMBOL_GPL(mark_page_dirty); |
| 1815 | 1818 | ||
| 1819 | static int kvm_vcpu_check_block(struct kvm_vcpu *vcpu) | ||
| 1820 | { | ||
| 1821 | if (kvm_arch_vcpu_runnable(vcpu)) { | ||
| 1822 | kvm_make_request(KVM_REQ_UNHALT, vcpu); | ||
| 1823 | return -EINTR; | ||
| 1824 | } | ||
| 1825 | if (kvm_cpu_has_pending_timer(vcpu)) | ||
| 1826 | return -EINTR; | ||
| 1827 | if (signal_pending(current)) | ||
| 1828 | return -EINTR; | ||
| 1829 | |||
| 1830 | return 0; | ||
| 1831 | } | ||
| 1832 | |||
| 1816 | /* | 1833 | /* |
| 1817 | * The vCPU has executed a HLT instruction with in-kernel mode enabled. | 1834 | * The vCPU has executed a HLT instruction with in-kernel mode enabled. |
| 1818 | */ | 1835 | */ |
| 1819 | void kvm_vcpu_block(struct kvm_vcpu *vcpu) | 1836 | void kvm_vcpu_block(struct kvm_vcpu *vcpu) |
| 1820 | { | 1837 | { |
| 1838 | ktime_t start, cur; | ||
| 1821 | DEFINE_WAIT(wait); | 1839 | DEFINE_WAIT(wait); |
| 1840 | bool waited = false; | ||
| 1841 | |||
| 1842 | start = cur = ktime_get(); | ||
| 1843 | if (halt_poll_ns) { | ||
| 1844 | ktime_t stop = ktime_add_ns(ktime_get(), halt_poll_ns); | ||
| 1845 | do { | ||
| 1846 | /* | ||
| 1847 | * This sets KVM_REQ_UNHALT if an interrupt | ||
| 1848 | * arrives. | ||
| 1849 | */ | ||
| 1850 | if (kvm_vcpu_check_block(vcpu) < 0) { | ||
| 1851 | ++vcpu->stat.halt_successful_poll; | ||
| 1852 | goto out; | ||
| 1853 | } | ||
| 1854 | cur = ktime_get(); | ||
| 1855 | } while (single_task_running() && ktime_before(cur, stop)); | ||
| 1856 | } | ||
| 1822 | 1857 | ||
| 1823 | for (;;) { | 1858 | for (;;) { |
| 1824 | prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); | 1859 | prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); |
| 1825 | 1860 | ||
| 1826 | if (kvm_arch_vcpu_runnable(vcpu)) { | 1861 | if (kvm_vcpu_check_block(vcpu) < 0) |
| 1827 | kvm_make_request(KVM_REQ_UNHALT, vcpu); | ||
| 1828 | break; | ||
| 1829 | } | ||
| 1830 | if (kvm_cpu_has_pending_timer(vcpu)) | ||
| 1831 | break; | ||
| 1832 | if (signal_pending(current)) | ||
| 1833 | break; | 1862 | break; |
| 1834 | 1863 | ||
| 1864 | waited = true; | ||
| 1835 | schedule(); | 1865 | schedule(); |
| 1836 | } | 1866 | } |
| 1837 | 1867 | ||
| 1838 | finish_wait(&vcpu->wq, &wait); | 1868 | finish_wait(&vcpu->wq, &wait); |
| 1869 | cur = ktime_get(); | ||
| 1870 | |||
| 1871 | out: | ||
| 1872 | trace_kvm_vcpu_wakeup(ktime_to_ns(cur) - ktime_to_ns(start), waited); | ||
| 1839 | } | 1873 | } |
| 1840 | EXPORT_SYMBOL_GPL(kvm_vcpu_block); | 1874 | EXPORT_SYMBOL_GPL(kvm_vcpu_block); |
| 1841 | 1875 | ||
