Commit 05bac030 authored by Mao Minkai's avatar Mao Minkai Committed by guzitao
Browse files

sw64: fix KVM support

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I56WV8



--------------------------------

Modify generic headers and routines for SW64 KVM support.

Signed-off-by: default avatarMao Minkai <maominkai@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent 57531837
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -1766,6 +1766,9 @@ static inline bool kvm_is_error_gpa(struct kvm *kvm, gpa_t gpa)
enum kvm_stat_kind {
	KVM_STAT_VM,
	KVM_STAT_VCPU,
#ifdef CONFIG_SW64
	KVM_STAT_DFX_SW64, /* Detail For vcpu stat EXtension */
#endif
};

struct kvm_stat_data {
@@ -1916,6 +1919,21 @@ struct _kvm_stats_desc {
			HALT_POLL_HIST_COUNT),				       \
	STATS_DESC_IBOOLEAN(VCPU_GENERIC, blocking)

#ifdef CONFIG_SW64
enum dfx_sw64_stat_kind {
	DFX_SW64_STAT_U64,
	DFX_SW64_STAT_CPUTIME,
};

/* Detail For vcpu stat EXtension debugfs item */
struct dfx_sw64_kvm_stats_debugfs_item {
	const char *name;
	int offset;
	enum dfx_sw64_stat_kind dfx_kind;
	struct dentry *dentry;
};
extern struct dfx_sw64_kvm_stats_debugfs_item dfx_sw64_debugfs_entries[];
#endif
extern struct dentry *kvm_debugfs_dir;

#ifdef CONFIG_ARCH_VCPU_STAT
+5 −0
Original line number Diff line number Diff line
@@ -1563,6 +1563,11 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_COUNTER_OFFSET */
#define KVM_ARM_SET_COUNTER_OFFSET _IOW(KVMIO,  0xb5, struct kvm_arm_counter_offset)

/* ioctl for SW vcpu init*/
#define KVM_SW64_VCPU_INIT	  _IO(KVMIO,  0xba)
#define KVM_SW64_GET_VCB          _IO(KVMIO,  0xbc)
#define KVM_SW64_SET_VCB          _IO(KVMIO,  0xbd)

/* ioctl for vm fd */
#define KVM_CREATE_DEVICE	  _IOWR(KVMIO,  0xe0, struct kvm_create_device)

+126 −0
Original line number Diff line number Diff line
@@ -161,6 +161,11 @@ __weak struct dfx_kvm_stats_debugfs_item dfx_debugfs_entries[] = {
};
#endif

#ifdef CONFIG_SW64
#define DFX_SW64_MAX_VCPU            1024
#define DFX_SW64_MAX_VCPU_STAT_SIZE  1024
#endif

__weak void kvm_arch_guest_memory_reclaimed(struct kvm *kvm)
{
}
@@ -4171,6 +4176,9 @@ static long kvm_vcpu_ioctl(struct file *filp,
#if defined(CONFIG_ARCH_VCPU_STAT)
			vcpu->stat.pid = current->pid;
#endif /* defined(CONFIG_ARCH_VCPU_STAT) */
#ifdef CONFIG_SW64
			vcpu->stat.pid = current->pid;
#endif
		}
		r = kvm_arch_vcpu_ioctl_run(vcpu);
		trace_kvm_userspace_exit(vcpu->run->exit_reason, r);
@@ -5766,6 +5774,10 @@ static int kvm_stat_data_get(void *data, u64 *val)
		r = kvm_get_stat_per_vcpu(stat_data->kvm,
					  stat_data->desc->desc.offset, val);
		break;
#ifdef CONFIG_SW64
	case KVM_STAT_DFX_SW64:
		break;
#endif
	}

	return r;
@@ -5788,6 +5800,10 @@ static int kvm_stat_data_clear(void *data, u64 val)
		r = kvm_clear_stat_per_vcpu(stat_data->kvm,
					    stat_data->desc->desc.offset);
		break;
#ifdef CONFIG_SW64
	case KVM_STAT_DFX_SW64:
		break;
#endif
	}

	return r;
@@ -5995,6 +6011,116 @@ DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, vcpu_stat_clear,
			"%llu\n");
DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_readonly_fops, vcpu_stat_get, NULL, "%llu\n");

#ifdef CONFIG_SW64
void __weak kvm_arch_vcpu_stat_reset(struct kvm_vcpu_stat *vcpu_stat)
{
}

/*
 * copy of seq_buf_alloc of kernel, kernel not export it
 */
static void *dfx_sw64_seq_buf_alloc(unsigned long size)
{
	return kvmalloc(size, GFP_KERNEL_ACCOUNT);
}

static void dfx_sw64_seq_buf_free(const void *buf)
{
	kvfree(buf);
}

static int dfx_sw64_seq_buf_alloc_vcpu(struct seq_file *p, int vcpu_nr)
{
	char *buf;
	size_t size;

	size = (vcpu_nr + 1) * DFX_SW64_MAX_VCPU_STAT_SIZE;
	buf = dfx_sw64_seq_buf_alloc(size);
	if (!buf)
		return -ENOMEM;
	if (p->buf)
		dfx_sw64_seq_buf_free(p->buf);
	p->buf = buf;
	p->size = size;
	return 0;
}

static int __dfx_sw64_vcpu_stats_get(struct seq_file *p, void *v)
{
	struct kvm *kvm;
	struct kvm_vcpu *vcpu;
	struct kvm_vcpu_stat *vcpu_stats;
	struct dfx_sw64_kvm_stats_debugfs_item *dp;
	int vcpu_nr = 0;
	int index = 0;
	unsigned long i;

	mutex_lock(&kvm_lock);
	list_for_each_entry(kvm, &vm_list, vm_list)
		kvm_for_each_vcpu(i, vcpu, kvm) {
			vcpu_nr++;
		}
	mutex_unlock(&kvm_lock);
	vcpu_nr = min(vcpu_nr, DFX_SW64_MAX_VCPU);
	if (!vcpu_nr) {
		seq_putc(p, '\n');
		return 0;
	}

	if (dfx_sw64_seq_buf_alloc_vcpu(p, vcpu_nr))
		return -ENOMEM;

	vcpu_stats = vmalloc(vcpu_nr * sizeof(struct kvm_vcpu_stat));
	if (!vcpu_stats)
		return -ENOMEM;

	mutex_lock(&kvm_lock);
	list_for_each_entry(kvm, &vm_list, vm_list) {
		kvm_for_each_vcpu(i, vcpu, kvm) {
			if (index >= vcpu_nr)
				break;
			memcpy(vcpu_stats + index, &(vcpu->stat),
			       sizeof(struct kvm_vcpu_stat));
			kvm_arch_vcpu_stat_reset(&vcpu->stat);
			++index;
		}
	}
	mutex_unlock(&kvm_lock);
	for (i = 0; i < vcpu_nr; i++) {
		for (dp = dfx_sw64_debugfs_entries; dp->name; ++dp) {
			switch (dp->dfx_kind) {
			case DFX_SW64_STAT_U64:
				seq_put_decimal_ull(p, " ",
						*(u64 *)((void *)&vcpu_stats[i] + dp->offset));
				break;
			case DFX_SW64_STAT_CPUTIME:
				pr_warn("DFX_SW64_STAT_CPUTIME not supported currently!");
				break;
			default:
				pr_warn("Bad dfx_sw64_kind in dfx_debugfs_entries!");
				break;
			}
		}
		seq_putc(p, '\n');
	}

	vfree(vcpu_stats);
	return 0;
}

static int dfx_sw64_vcpu_stats_open(struct inode *inode, struct file *file)
{
	return single_open(file, __dfx_sw64_vcpu_stats_get, NULL);
}

static const struct file_operations dfx_sw64_stat_fops = {
	.open           = dfx_sw64_vcpu_stats_open,
	.read           = seq_read,
	.llseek         = seq_lseek,
	.release        = single_release,
};
#endif

static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm)
{
	struct kobj_uevent_env *env;