Commit a443e260 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-s390-next-6.5-1' of...

Merge tag 'kvm-s390-next-6.5-1' of https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

* New uvdevice secret API
* New CMM selftest
* cmm fix
* diag 9c racy access of target cpu fix
parents 6995e2de db54dfc9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -47,6 +47,10 @@ void uv_query_info(void)
		uv_info.conf_dump_finalize_len = uvcb.conf_dump_finalize_len;
		uv_info.supp_att_req_hdr_ver = uvcb.supp_att_req_hdr_ver;
		uv_info.supp_att_pflags = uvcb.supp_att_pflags;
		uv_info.supp_add_secret_req_ver = uvcb.supp_add_secret_req_ver;
		uv_info.supp_add_secret_pcf = uvcb.supp_add_secret_pcf;
		uv_info.supp_secret_types = uvcb.supp_secret_types;
		uv_info.max_secrets = uvcb.max_secrets;
	}

#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
+30 −2
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@
#define UVC_CMD_SET_SHARED_ACCESS	0x1000
#define UVC_CMD_REMOVE_SHARED_ACCESS	0x1001
#define UVC_CMD_RETR_ATTEST		0x1020
#define UVC_CMD_ADD_SECRET		0x1031
#define UVC_CMD_LIST_SECRETS		0x1033
#define UVC_CMD_LOCK_SECRETS		0x1034

/* Bits in installed uv calls */
enum uv_cmds_inst {
@@ -88,6 +91,9 @@ enum uv_cmds_inst {
	BIT_UVC_CMD_DUMP_CPU = 26,
	BIT_UVC_CMD_DUMP_COMPLETE = 27,
	BIT_UVC_CMD_RETR_ATTEST = 28,
	BIT_UVC_CMD_ADD_SECRET = 29,
	BIT_UVC_CMD_LIST_SECRETS = 30,
	BIT_UVC_CMD_LOCK_SECRETS = 31,
};

enum uv_feat_ind {
@@ -117,7 +123,7 @@ struct uv_cb_qui {
	u32 reserved70[3];			/* 0x0070 */
	u32 max_num_sec_conf;			/* 0x007c */
	u64 max_guest_stor_addr;		/* 0x0080 */
	u8  reserved88[158 - 136];		/* 0x0088 */
	u8  reserved88[0x9e - 0x88];		/* 0x0088 */
	u16 max_guest_cpu_id;			/* 0x009e */
	u64 uv_feature_indications;		/* 0x00a0 */
	u64 reserveda8;				/* 0x00a8 */
@@ -129,7 +135,12 @@ struct uv_cb_qui {
	u64 reservedd8;				/* 0x00d8 */
	u64 supp_att_req_hdr_ver;		/* 0x00e0 */
	u64 supp_att_pflags;			/* 0x00e8 */
	u8 reservedf0[256 - 240];		/* 0x00f0 */
	u64 reservedf0;				/* 0x00f0 */
	u64 supp_add_secret_req_ver;		/* 0x00f8 */
	u64 supp_add_secret_pcf;		/* 0x0100 */
	u64 supp_secret_types;			/* 0x0180 */
	u16 max_secrets;			/* 0x0110 */
	u8 reserved112[0x120 - 0x112];		/* 0x0112 */
} __packed __aligned(8);

/* Initialize Ultravisor */
@@ -292,6 +303,19 @@ struct uv_cb_dump_complete {
	u64 reserved30[5];
} __packed __aligned(8);

/*
 * A common UV call struct for pv guests that contains a single address
 * Examples:
 * Add Secret
 * List Secrets
 */
struct uv_cb_guest_addr {
	struct uv_cb_header header;
	u64 reserved08[3];
	u64 addr;
	u64 reserved28[4];
} __packed __aligned(8);

static inline int __uv_call(unsigned long r1, unsigned long r2)
{
	int cc;
@@ -365,6 +389,10 @@ struct uv_info {
	unsigned long conf_dump_finalize_len;
	unsigned long supp_att_req_hdr_ver;
	unsigned long supp_att_pflags;
	unsigned long supp_add_secret_req_ver;
	unsigned long supp_add_secret_pcf;
	unsigned long supp_secret_types;
	unsigned short max_secrets;
};

extern struct uv_info uv_info;
+52 −1
Original line number Diff line number Diff line
@@ -32,6 +32,33 @@ struct uvio_attest {
	__u16 reserved136;				/* 0x0136 */
};

/**
 * uvio_uvdev_info - Information of supported functions
 * @supp_uvio_cmds - supported IOCTLs by this device
 * @supp_uv_cmds - supported UVCs corresponding to the IOCTL
 *
 * UVIO request to get information about supported request types by this
 * uvdevice and the Ultravisor.  Everything is output. Bits are in LSB0
 * ordering.  If the bit is set in both, @supp_uvio_cmds and @supp_uv_cmds, the
 * uvdevice and the Ultravisor support that call.
 *
 * Note that bit 0 (UVIO_IOCTL_UVDEV_INFO_NR) is always zero for `supp_uv_cmds`
 * as there is no corresponding UV-call.
 */
struct uvio_uvdev_info {
	/*
	 * If bit `n` is set, this device supports the IOCTL with nr `n`.
	 */
	__u64 supp_uvio_cmds;
	/*
	 * If bit `n` is set, the Ultravisor(UV) supports the UV-call
	 * corresponding to the IOCTL with nr `n` in the calling contextx (host
	 * or guest).  The value is only valid if the corresponding bit in
	 * @supp_uvio_cmds is set as well.
	 */
	__u64 supp_uv_cmds;
};

/*
 * The following max values define an upper length for the IOCTL in/out buffers.
 * However, they do not represent the maximum the Ultravisor allows which is
@@ -42,10 +69,34 @@ struct uvio_attest {
#define UVIO_ATT_ARCB_MAX_LEN		0x100000
#define UVIO_ATT_MEASUREMENT_MAX_LEN	0x8000
#define UVIO_ATT_ADDITIONAL_MAX_LEN	0x8000
#define UVIO_ADD_SECRET_MAX_LEN		0x100000
#define UVIO_LIST_SECRETS_LEN		0x1000

#define UVIO_DEVICE_NAME "uv"
#define UVIO_TYPE_UVC 'u'

#define UVIO_IOCTL_ATT _IOWR(UVIO_TYPE_UVC, 0x01, struct uvio_ioctl_cb)
enum UVIO_IOCTL_NR {
	UVIO_IOCTL_UVDEV_INFO_NR = 0x00,
	UVIO_IOCTL_ATT_NR,
	UVIO_IOCTL_ADD_SECRET_NR,
	UVIO_IOCTL_LIST_SECRETS_NR,
	UVIO_IOCTL_LOCK_SECRETS_NR,
	/* must be the last entry */
	UVIO_IOCTL_NUM_IOCTLS
};

#define UVIO_IOCTL(nr)		_IOWR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb)
#define UVIO_IOCTL_UVDEV_INFO	UVIO_IOCTL(UVIO_IOCTL_UVDEV_INFO_NR)
#define UVIO_IOCTL_ATT		UVIO_IOCTL(UVIO_IOCTL_ATT_NR)
#define UVIO_IOCTL_ADD_SECRET	UVIO_IOCTL(UVIO_IOCTL_ADD_SECRET_NR)
#define UVIO_IOCTL_LIST_SECRETS	UVIO_IOCTL(UVIO_IOCTL_LIST_SECRETS_NR)
#define UVIO_IOCTL_LOCK_SECRETS	UVIO_IOCTL(UVIO_IOCTL_LOCK_SECRETS_NR)

#define UVIO_SUPP_CALL(nr)	(1ULL << (nr))
#define UVIO_SUPP_UDEV_INFO	UVIO_SUPP_CALL(UVIO_IOCTL_UDEV_INFO_NR)
#define UVIO_SUPP_ATT		UVIO_SUPP_CALL(UVIO_IOCTL_ATT_NR)
#define UVIO_SUPP_ADD_SECRET	UVIO_SUPP_CALL(UVIO_IOCTL_ADD_SECRET_NR)
#define UVIO_SUPP_LIST_SECRETS	UVIO_SUPP_CALL(UVIO_IOCTL_LIST_SECRETS_NR)
#define UVIO_SUPP_LOCK_SECRETS	UVIO_SUPP_CALL(UVIO_IOCTL_LOCK_SECRETS_NR)

#endif /* __S390_ASM_UVDEVICE_H */
+75 −33
Original line number Diff line number Diff line
@@ -23,12 +23,20 @@
int __bootdata_preserved(prot_virt_guest);
#endif

/*
 * uv_info contains both host and guest information but it's currently only
 * expected to be used within modules if it's the KVM module or for
 * any PV guest module.
 *
 * The kernel itself will write these values once in uv_query_info()
 * and then make some of them readable via a sysfs interface.
 */
struct uv_info __bootdata_preserved(uv_info);
EXPORT_SYMBOL(uv_info);

#if IS_ENABLED(CONFIG_KVM)
int __bootdata_preserved(prot_virt_host);
EXPORT_SYMBOL(prot_virt_host);
EXPORT_SYMBOL(uv_info);

static int __init uv_init(phys_addr_t stor_base, unsigned long stor_len)
{
@@ -460,9 +468,9 @@ EXPORT_SYMBOL_GPL(arch_make_page_accessible);

#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM)
static ssize_t uv_query_facilities(struct kobject *kobj,
				   struct kobj_attribute *attr, char *page)
				   struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n",
	return sysfs_emit(buf, "%lx\n%lx\n%lx\n%lx\n",
			  uv_info.inst_calls_list[0],
			  uv_info.inst_calls_list[1],
			  uv_info.inst_calls_list[2],
@@ -491,30 +499,27 @@ static struct kobj_attribute uv_query_supp_se_hdr_pcf_attr =
	__ATTR(supp_se_hdr_pcf, 0444, uv_query_supp_se_hdr_pcf, NULL);

static ssize_t uv_query_dump_cpu_len(struct kobject *kobj,
				     struct kobj_attribute *attr, char *page)
				     struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%lx\n",
			uv_info.guest_cpu_stor_len);
	return sysfs_emit(buf, "%lx\n", uv_info.guest_cpu_stor_len);
}

static struct kobj_attribute uv_query_dump_cpu_len_attr =
	__ATTR(uv_query_dump_cpu_len, 0444, uv_query_dump_cpu_len, NULL);

static ssize_t uv_query_dump_storage_state_len(struct kobject *kobj,
					       struct kobj_attribute *attr, char *page)
					       struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%lx\n",
			uv_info.conf_dump_storage_state_len);
	return sysfs_emit(buf, "%lx\n", uv_info.conf_dump_storage_state_len);
}

static struct kobj_attribute uv_query_dump_storage_state_len_attr =
	__ATTR(dump_storage_state_len, 0444, uv_query_dump_storage_state_len, NULL);

static ssize_t uv_query_dump_finalize_len(struct kobject *kobj,
					  struct kobj_attribute *attr, char *page)
					  struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%lx\n",
			uv_info.conf_dump_finalize_len);
	return sysfs_emit(buf, "%lx\n", uv_info.conf_dump_finalize_len);
}

static struct kobj_attribute uv_query_dump_finalize_len_attr =
@@ -530,53 +535,86 @@ static struct kobj_attribute uv_query_feature_indications_attr =
	__ATTR(feature_indications, 0444, uv_query_feature_indications, NULL);

static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
				       struct kobj_attribute *attr, char *page)
				       struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%d\n",
			uv_info.max_guest_cpu_id + 1);
	return sysfs_emit(buf, "%d\n", uv_info.max_guest_cpu_id + 1);
}

static struct kobj_attribute uv_query_max_guest_cpus_attr =
	__ATTR(max_cpus, 0444, uv_query_max_guest_cpus, NULL);

static ssize_t uv_query_max_guest_vms(struct kobject *kobj,
				      struct kobj_attribute *attr, char *page)
				      struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%d\n",
			uv_info.max_num_sec_conf);
	return sysfs_emit(buf, "%d\n", uv_info.max_num_sec_conf);
}

static struct kobj_attribute uv_query_max_guest_vms_attr =
	__ATTR(max_guests, 0444, uv_query_max_guest_vms, NULL);

static ssize_t uv_query_max_guest_addr(struct kobject *kobj,
				       struct kobj_attribute *attr, char *page)
				       struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%lx\n",
			uv_info.max_sec_stor_addr);
	return sysfs_emit(buf, "%lx\n", uv_info.max_sec_stor_addr);
}

static struct kobj_attribute uv_query_max_guest_addr_attr =
	__ATTR(max_address, 0444, uv_query_max_guest_addr, NULL);

static ssize_t uv_query_supp_att_req_hdr_ver(struct kobject *kobj,
					     struct kobj_attribute *attr, char *page)
					     struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%lx\n", uv_info.supp_att_req_hdr_ver);
	return sysfs_emit(buf, "%lx\n", uv_info.supp_att_req_hdr_ver);
}

static struct kobj_attribute uv_query_supp_att_req_hdr_ver_attr =
	__ATTR(supp_att_req_hdr_ver, 0444, uv_query_supp_att_req_hdr_ver, NULL);

static ssize_t uv_query_supp_att_pflags(struct kobject *kobj,
					struct kobj_attribute *attr, char *page)
					struct kobj_attribute *attr, char *buf)
{
	return scnprintf(page, PAGE_SIZE, "%lx\n", uv_info.supp_att_pflags);
	return sysfs_emit(buf, "%lx\n", uv_info.supp_att_pflags);
}

static struct kobj_attribute uv_query_supp_att_pflags_attr =
	__ATTR(supp_att_pflags, 0444, uv_query_supp_att_pflags, NULL);

static ssize_t uv_query_supp_add_secret_req_ver(struct kobject *kobj,
						struct kobj_attribute *attr, char *buf)
{
	return sysfs_emit(buf, "%lx\n", uv_info.supp_add_secret_req_ver);
}

static struct kobj_attribute uv_query_supp_add_secret_req_ver_attr =
	__ATTR(supp_add_secret_req_ver, 0444, uv_query_supp_add_secret_req_ver, NULL);

static ssize_t uv_query_supp_add_secret_pcf(struct kobject *kobj,
					    struct kobj_attribute *attr, char *buf)
{
	return sysfs_emit(buf, "%lx\n", uv_info.supp_add_secret_pcf);
}

static struct kobj_attribute uv_query_supp_add_secret_pcf_attr =
	__ATTR(supp_add_secret_pcf, 0444, uv_query_supp_add_secret_pcf, NULL);

static ssize_t uv_query_supp_secret_types(struct kobject *kobj,
					  struct kobj_attribute *attr, char *buf)
{
	return sysfs_emit(buf, "%lx\n", uv_info.supp_secret_types);
}

static struct kobj_attribute uv_query_supp_secret_types_attr =
	__ATTR(supp_secret_types, 0444, uv_query_supp_secret_types, NULL);

static ssize_t uv_query_max_secrets(struct kobject *kobj,
				    struct kobj_attribute *attr, char *buf)
{
	return sysfs_emit(buf, "%d\n", uv_info.max_secrets);
}

static struct kobj_attribute uv_query_max_secrets_attr =
	__ATTR(max_secrets, 0444, uv_query_max_secrets, NULL);

static struct attribute *uv_query_attrs[] = {
	&uv_query_facilities_attr.attr,
	&uv_query_feature_indications_attr.attr,
@@ -590,6 +628,10 @@ static struct attribute *uv_query_attrs[] = {
	&uv_query_dump_cpu_len_attr.attr,
	&uv_query_supp_att_req_hdr_ver_attr.attr,
	&uv_query_supp_att_pflags_attr.attr,
	&uv_query_supp_add_secret_req_ver_attr.attr,
	&uv_query_supp_add_secret_pcf_attr.attr,
	&uv_query_supp_secret_types_attr.attr,
	&uv_query_max_secrets_attr.attr,
	NULL,
};

@@ -598,18 +640,18 @@ static struct attribute_group uv_query_attr_group = {
};

static ssize_t uv_is_prot_virt_guest(struct kobject *kobj,
				     struct kobj_attribute *attr, char *page)
				     struct kobj_attribute *attr, char *buf)
{
	int val = 0;

#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
	val = prot_virt_guest;
#endif
	return scnprintf(page, PAGE_SIZE, "%d\n", val);
	return sysfs_emit(buf, "%d\n", val);
}

static ssize_t uv_is_prot_virt_host(struct kobject *kobj,
				    struct kobj_attribute *attr, char *page)
				    struct kobj_attribute *attr, char *buf)
{
	int val = 0;

@@ -617,7 +659,7 @@ static ssize_t uv_is_prot_virt_host(struct kobject *kobj,
	val = prot_virt_host;
#endif

	return scnprintf(page, PAGE_SIZE, "%d\n", val);
	return sysfs_emit(buf, "%d\n", val);
}

static struct kobj_attribute uv_prot_virt_guest =
+5 −3
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ static int diag9c_forwarding_overrun(void)
static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu)
{
	struct kvm_vcpu *tcpu;
	int tcpu_cpu;
	int tid;

	tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
@@ -181,14 +182,15 @@ static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu)
		goto no_yield;

	/* target guest VCPU already running */
	if (READ_ONCE(tcpu->cpu) >= 0) {
	tcpu_cpu = READ_ONCE(tcpu->cpu);
	if (tcpu_cpu >= 0) {
		if (!diag9c_forwarding_hz || diag9c_forwarding_overrun())
			goto no_yield;

		/* target host CPU already running */
		if (!vcpu_is_preempted(tcpu->cpu))
		if (!vcpu_is_preempted(tcpu_cpu))
			goto no_yield;
		smp_yield_cpu(tcpu->cpu);
		smp_yield_cpu(tcpu_cpu);
		VCPU_EVENT(vcpu, 5,
			   "diag time slice end directed to %d: yield forwarded",
			   tid);
Loading