static LIST_HEAD(vm_list);
struct kvm_arch_ops *kvm_arch_ops;
-struct kvm_stat kvm_stat;
-EXPORT_SYMBOL_GPL(kvm_stat);
+
+#define STAT_OFFSET(x) offsetof(struct kvm_vcpu, stat.x)
static struct kvm_stats_debugfs_item {
const char *name;
- u32 *data;
+ int offset;
struct dentry *dentry;
} debugfs_entries[] = {
- { "pf_fixed", &kvm_stat.pf_fixed },
- { "pf_guest", &kvm_stat.pf_guest },
- { "tlb_flush", &kvm_stat.tlb_flush },
- { "invlpg", &kvm_stat.invlpg },
- { "exits", &kvm_stat.exits },
- { "io_exits", &kvm_stat.io_exits },
- { "mmio_exits", &kvm_stat.mmio_exits },
- { "signal_exits", &kvm_stat.signal_exits },
- { "irq_window", &kvm_stat.irq_window_exits },
- { "halt_exits", &kvm_stat.halt_exits },
- { "request_irq", &kvm_stat.request_irq_exits },
- { "irq_exits", &kvm_stat.irq_exits },
- { NULL, NULL }
+ { "pf_fixed", STAT_OFFSET(pf_fixed) },
+ { "pf_guest", STAT_OFFSET(pf_guest) },
+ { "tlb_flush", STAT_OFFSET(tlb_flush) },
+ { "invlpg", STAT_OFFSET(invlpg) },
+ { "exits", STAT_OFFSET(exits) },
+ { "io_exits", STAT_OFFSET(io_exits) },
+ { "mmio_exits", STAT_OFFSET(mmio_exits) },
+ { "signal_exits", STAT_OFFSET(signal_exits) },
+ { "irq_window", STAT_OFFSET(irq_window_exits) },
+ { "halt_exits", STAT_OFFSET(halt_exits) },
+ { "request_irq", STAT_OFFSET(request_irq_exits) },
+ { "irq_exits", STAT_OFFSET(irq_exits) },
+ { NULL }
};
static struct dentry *debugfs_dir;
.priority = 20, /* must be > scheduler priority */
};
+static u64 stat_get(void *_offset)
+{
+ unsigned offset = (long)_offset;
+ u64 total = 0;
+ struct kvm *kvm;
+ struct kvm_vcpu *vcpu;
+ int i;
+
+ spin_lock(&kvm_lock);
+ list_for_each_entry(kvm, &vm_list, vm_list)
+ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+ vcpu = &kvm->vcpus[i];
+ total += *(u32 *)((void *)vcpu + offset);
+ }
+ spin_unlock(&kvm_lock);
+ return total;
+}
+
+static void stat_set(void *offset, u64 val)
+{
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(stat_fops, stat_get, stat_set, "%llu\n");
+
static __init void kvm_init_debug(void)
{
struct kvm_stats_debugfs_item *p;
debugfs_dir = debugfs_create_dir("kvm", NULL);
for (p = debugfs_entries; p->name; ++p)
- p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir,
- p->data);
+ p->dentry = debugfs_create_file(p->name, 0444, debugfs_dir,
+ (void *)(long)p->offset,
+ &stat_fops);
}
static void kvm_exit_debug(void)
case EMULATE_DONE:
return 1;
case EMULATE_DO_MMIO:
- ++kvm_stat.mmio_exits;
+ ++vcpu->stat.mmio_exits;
kvm_run->exit_reason = KVM_EXIT_MMIO;
return 0;
case EMULATE_FAIL:
unsigned long count;
gva_t address = 0;
- ++kvm_stat.io_exits;
+ ++vcpu->stat.io_exits;
vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2;
return 1;
kvm_run->exit_reason = KVM_EXIT_HLT;
- ++kvm_stat.halt_exits;
+ ++vcpu->stat.halt_exits;
return 0;
}
*/
if (kvm_run->request_interrupt_window &&
!vcpu->irq_summary) {
- ++kvm_stat.irq_window_exits;
+ ++vcpu->stat.irq_window_exits;
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
return 0;
}
r = handle_exit(vcpu, kvm_run);
if (r > 0) {
if (signal_pending(current)) {
- ++kvm_stat.signal_exits;
+ ++vcpu->stat.signal_exits;
post_kvm_run_save(vcpu, kvm_run);
kvm_run->exit_reason = KVM_EXIT_INTR;
return -EINTR;
}
if (dm_request_for_irq_injection(vcpu, kvm_run)) {
- ++kvm_stat.request_irq_exits;
+ ++vcpu->stat.request_irq_exits;
post_kvm_run_save(vcpu, kvm_run);
kvm_run->exit_reason = KVM_EXIT_INTR;
return -EINTR;
{
uint32_t exit_int_info = vcpu->svm->vmcb->control.exit_int_info;
- ++kvm_stat.pf_guest;
+ ++vcpu->stat.pf_guest;
if (is_page_fault(exit_int_info)) {
case EMULATE_DONE:
return 1;
case EMULATE_DO_MMIO:
- ++kvm_stat.mmio_exits;
+ ++vcpu->stat.mmio_exits;
kvm_run->exit_reason = KVM_EXIT_MMIO;
return 0;
case EMULATE_FAIL:
static int handle_external_interrupt(struct kvm_vcpu *vcpu,
struct kvm_run *kvm_run)
{
- ++kvm_stat.irq_exits;
+ ++vcpu->stat.irq_exits;
return 1;
}
unsigned long count;
gva_t address;
- ++kvm_stat.io_exits;
+ ++vcpu->stat.io_exits;
exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
in = (exit_qualification & 8) != 0;
size = (exit_qualification & 7) + 1;
if (kvm_run->request_interrupt_window &&
!vcpu->irq_summary) {
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
- ++kvm_stat.irq_window_exits;
+ ++vcpu->stat.irq_window_exits;
return 0;
}
return 1;
return 1;
kvm_run->exit_reason = KVM_EXIT_HLT;
- ++kvm_stat.halt_exits;
+ ++vcpu->stat.halt_exits;
return 0;
}
reload_tss();
}
- ++kvm_stat.exits;
+ ++vcpu->stat.exits;
#ifdef CONFIG_X86_64
if (is_long_mode(vcpu)) {
if (r > 0) {
/* Give scheduler a change to reschedule. */
if (signal_pending(current)) {
- ++kvm_stat.signal_exits;
+ ++vcpu->stat.signal_exits;
post_kvm_run_save(vcpu, kvm_run);
kvm_run->exit_reason = KVM_EXIT_INTR;
return -EINTR;
}
if (dm_request_for_irq_injection(vcpu, kvm_run)) {
- ++kvm_stat.request_irq_exits;
+ ++vcpu->stat.request_irq_exits;
post_kvm_run_save(vcpu, kvm_run);
kvm_run->exit_reason = KVM_EXIT_INTR;
return -EINTR;
{
u32 vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
- ++kvm_stat.pf_guest;
+ ++vcpu->stat.pf_guest;
if (is_page_fault(vect_info)) {
printk(KERN_DEBUG "inject_page_fault: "