diff options
Diffstat (limited to 'virt')
| -rw-r--r-- | virt/kvm/kvm_main.c | 104 | 
1 files changed, 76 insertions, 28 deletions
| diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c8d0028df4ac..3dcc2abbfc60 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -115,7 +115,6 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_running_vcpu);  struct dentry *kvm_debugfs_dir;  EXPORT_SYMBOL_GPL(kvm_debugfs_dir); -static int kvm_debugfs_num_entries;  static const struct file_operations stat_fops_per_vm;  static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, @@ -860,9 +859,24 @@ static void kvm_free_memslots(struct kvm *kvm, struct kvm_memslots *slots)  	kvfree(slots);  } +static umode_t kvm_stats_debugfs_mode(const struct _kvm_stats_desc *pdesc) +{ +	switch (pdesc->desc.flags & KVM_STATS_TYPE_MASK) { +	case KVM_STATS_TYPE_INSTANT: +		return 0444; +	case KVM_STATS_TYPE_CUMULATIVE: +	case KVM_STATS_TYPE_PEAK: +	default: +		return 0644; +	} +} + +  static void kvm_destroy_vm_debugfs(struct kvm *kvm)  {  	int i; +	int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc + +				      kvm_vcpu_stats_header.num_desc;  	if (!kvm->debugfs_dentry)  		return; @@ -880,7 +894,10 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)  {  	char dir_name[ITOA_MAX_LEN * 2];  	struct kvm_stat_data *stat_data; -	struct kvm_stats_debugfs_item *p; +	const struct _kvm_stats_desc *pdesc; +	int i; +	int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc + +				      kvm_vcpu_stats_header.num_desc;  	if (!debugfs_initialized())  		return 0; @@ -894,15 +911,32 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)  	if (!kvm->debugfs_stat_data)  		return -ENOMEM; -	for (p = debugfs_entries; p->name; p++) { +	for (i = 0; i < kvm_vm_stats_header.num_desc; ++i) { +		pdesc = &kvm_vm_stats_desc[i];  		stat_data = kzalloc(sizeof(*stat_data), GFP_KERNEL_ACCOUNT);  		if (!stat_data)  			return -ENOMEM;  		stat_data->kvm = kvm; -		stat_data->dbgfs_item = p; -		kvm->debugfs_stat_data[p - debugfs_entries] = stat_data; -		debugfs_create_file(p->name, KVM_DBGFS_GET_MODE(p), +		stat_data->desc = pdesc; +		stat_data->kind = KVM_STAT_VM; +		kvm->debugfs_stat_data[i] = stat_data; +		debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), +				    kvm->debugfs_dentry, stat_data, +				    &stat_fops_per_vm); +	} + +	for (i = 0; i < kvm_vcpu_stats_header.num_desc; ++i) { +		pdesc = &kvm_vcpu_stats_desc[i]; +		stat_data = kzalloc(sizeof(*stat_data), GFP_KERNEL_ACCOUNT); +		if (!stat_data) +			return -ENOMEM; + +		stat_data->kvm = kvm; +		stat_data->desc = pdesc; +		stat_data->kind = KVM_STAT_VCPU; +		kvm->debugfs_stat_data[i] = stat_data; +		debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc),  				    kvm->debugfs_dentry, stat_data,  				    &stat_fops_per_vm);  	} @@ -4900,7 +4934,7 @@ static int kvm_debugfs_open(struct inode *inode, struct file *file,  		return -ENOENT;  	if (simple_attr_open(inode, file, get, -		    KVM_DBGFS_GET_MODE(stat_data->dbgfs_item) & 0222 +		    kvm_stats_debugfs_mode(stat_data->desc) & 0222  		    ? set : NULL,  		    fmt)) {  		kvm_put_kvm(stat_data->kvm); @@ -4923,14 +4957,14 @@ static int kvm_debugfs_release(struct inode *inode, struct file *file)  static int kvm_get_stat_per_vm(struct kvm *kvm, size_t offset, u64 *val)  { -	*val = *(u64 *)((void *)kvm + offset); +	*val = *(u64 *)((void *)(&kvm->stat) + offset);  	return 0;  }  static int kvm_clear_stat_per_vm(struct kvm *kvm, size_t offset)  { -	*(u64 *)((void *)kvm + offset) = 0; +	*(u64 *)((void *)(&kvm->stat) + offset) = 0;  	return 0;  } @@ -4943,7 +4977,7 @@ static int kvm_get_stat_per_vcpu(struct kvm *kvm, size_t offset, u64 *val)  	*val = 0;  	kvm_for_each_vcpu(i, vcpu, kvm) -		*val += *(u64 *)((void *)vcpu + offset); +		*val += *(u64 *)((void *)(&vcpu->stat) + offset);  	return 0;  } @@ -4954,7 +4988,7 @@ static int kvm_clear_stat_per_vcpu(struct kvm *kvm, size_t offset)  	struct kvm_vcpu *vcpu;  	kvm_for_each_vcpu(i, vcpu, kvm) -		*(u64 *)((void *)vcpu + offset) = 0; +		*(u64 *)((void *)(&vcpu->stat) + offset) = 0;  	return 0;  } @@ -4964,14 +4998,14 @@ static int kvm_stat_data_get(void *data, u64 *val)  	int r = -EFAULT;  	struct kvm_stat_data *stat_data = (struct kvm_stat_data *)data; -	switch (stat_data->dbgfs_item->kind) { +	switch (stat_data->kind) {  	case KVM_STAT_VM:  		r = kvm_get_stat_per_vm(stat_data->kvm, -					stat_data->dbgfs_item->offset, val); +					stat_data->desc->desc.offset, val);  		break;  	case KVM_STAT_VCPU:  		r = kvm_get_stat_per_vcpu(stat_data->kvm, -					  stat_data->dbgfs_item->offset, val); +					  stat_data->desc->desc.offset, val);  		break;  	} @@ -4986,14 +5020,14 @@ static int kvm_stat_data_clear(void *data, u64 val)  	if (val)  		return -EINVAL; -	switch (stat_data->dbgfs_item->kind) { +	switch (stat_data->kind) {  	case KVM_STAT_VM:  		r = kvm_clear_stat_per_vm(stat_data->kvm, -					  stat_data->dbgfs_item->offset); +					  stat_data->desc->desc.offset);  		break;  	case KVM_STAT_VCPU:  		r = kvm_clear_stat_per_vcpu(stat_data->kvm, -					    stat_data->dbgfs_item->offset); +					    stat_data->desc->desc.offset);  		break;  	} @@ -5050,6 +5084,7 @@ static int vm_stat_clear(void *_offset, u64 val)  }  DEFINE_SIMPLE_ATTRIBUTE(vm_stat_fops, vm_stat_get, vm_stat_clear, "%llu\n"); +DEFINE_SIMPLE_ATTRIBUTE(vm_stat_readonly_fops, vm_stat_get, NULL, "%llu\n");  static int vcpu_stat_get(void *_offset, u64 *val)  { @@ -5086,11 +5121,7 @@ static int vcpu_stat_clear(void *_offset, u64 val)  DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, vcpu_stat_clear,  			"%llu\n"); - -static const struct file_operations *stat_fops[] = { -	[KVM_STAT_VCPU] = &vcpu_stat_fops, -	[KVM_STAT_VM]   = &vm_stat_fops, -}; +DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_readonly_fops, vcpu_stat_get, NULL, "%llu\n");  static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm)  { @@ -5144,15 +5175,32 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm)  static void kvm_init_debug(void)  { -	struct kvm_stats_debugfs_item *p; +	const struct file_operations *fops; +	const struct _kvm_stats_desc *pdesc; +	int i;  	kvm_debugfs_dir = debugfs_create_dir("kvm", NULL); -	kvm_debugfs_num_entries = 0; -	for (p = debugfs_entries; p->name; ++p, kvm_debugfs_num_entries++) { -		debugfs_create_file(p->name, KVM_DBGFS_GET_MODE(p), -				    kvm_debugfs_dir, (void *)(long)p->offset, -				    stat_fops[p->kind]); +	for (i = 0; i < kvm_vm_stats_header.num_desc; ++i) { +		pdesc = &kvm_vm_stats_desc[i]; +		if (kvm_stats_debugfs_mode(pdesc) & 0222) +			fops = &vm_stat_fops; +		else +			fops = &vm_stat_readonly_fops; +		debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), +				kvm_debugfs_dir, +				(void *)(long)pdesc->desc.offset, fops); +	} + +	for (i = 0; i < kvm_vcpu_stats_header.num_desc; ++i) { +		pdesc = &kvm_vcpu_stats_desc[i]; +		if (kvm_stats_debugfs_mode(pdesc) & 0222) +			fops = &vcpu_stat_fops; +		else +			fops = &vcpu_stat_readonly_fops; +		debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), +				kvm_debugfs_dir, +				(void *)(long)pdesc->desc.offset, fops);  	}  } |