Commit 46030379 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Heiko Carstens
Browse files

s390/ap: Restrict driver_override versus apmask and aqmask use



Introduce a restriction for the driver_override feature versus apmask
and aqmask:
- driver_override is only allowed when the apmask and aqmask values
  both are default (=0xffff..ffff).
- apmask and aqmask modifications are only allowed when there is no
  driver_override on any AP device active.
So in the end the user is restricted to choose to either use
apmask/apmask to divide the AP devices into host owned and vfio owned
or use the driver_override feature but not mix these two approaches.

Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarHolger Dengler <dengler@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 8babcc2b
Loading
Loading
Loading
Loading
+34 −3
Original line number Diff line number Diff line
@@ -86,8 +86,13 @@ DEFINE_SPINLOCK(ap_queues_lock);
/* Default permissions (ioctl, card and domain masking) */
struct ap_perms ap_perms;
EXPORT_SYMBOL(ap_perms);
/* true if apmask and/or aqmask are NOT default */
bool ap_apmask_aqmask_in_use;
/* counter for how many driver_overrides are currently active */
int ap_driver_override_ctr;
/*
 * Mutex for consistent read and write of the ap_perms struct
 * Mutex for consistent read and write of the ap_perms struct,
 * ap_apmask_aqmask_in_use, ap_driver_override_ctr
 * and the ap bus sysfs attributes apmask and aqmask.
 */
DEFINE_MUTEX(ap_attr_mutex);
@@ -1542,18 +1547,31 @@ static int apmask_commit(unsigned long *newapm)

	memcpy(ap_perms.apm, newapm, APMASKSIZE);

	/*
	 * Update ap_apmask_aqmask_in_use. Note that the
	 * ap_attr_mutex has to be obtained here.
	 */
	ap_apmask_aqmask_in_use =
		bitmap_full(ap_perms.apm, AP_DEVICES) &&
		bitmap_full(ap_perms.aqm, AP_DOMAINS) ?
		false : true;

	return 0;
}

static ssize_t apmask_store(const struct bus_type *bus, const char *buf,
			    size_t count)
{
	int rc, changes = 0;
	DECLARE_BITMAP(newapm, AP_DEVICES);
	int rc = -EINVAL, changes = 0;

	if (mutex_lock_interruptible(&ap_attr_mutex))
		return -ERESTARTSYS;

	/* Do not allow apmask/aqmask if driver override is active */
	if (ap_driver_override_ctr)
		goto done;

	rc = ap_parse_bitmap_str(buf, ap_perms.apm, AP_DEVICES, newapm);
	if (rc)
		goto done;
@@ -1636,18 +1654,31 @@ static int aqmask_commit(unsigned long *newaqm)

	memcpy(ap_perms.aqm, newaqm, AQMASKSIZE);

	/*
	 * Update ap_apmask_aqmask_in_use. Note that the
	 * ap_attr_mutex has to be obtained here.
	 */
	ap_apmask_aqmask_in_use =
		bitmap_full(ap_perms.apm, AP_DEVICES) &&
		bitmap_full(ap_perms.aqm, AP_DOMAINS) ?
		false : true;

	return 0;
}

static ssize_t aqmask_store(const struct bus_type *bus, const char *buf,
			    size_t count)
{
	int rc, changes = 0;
	DECLARE_BITMAP(newaqm, AP_DOMAINS);
	int rc = -EINVAL, changes = 0;

	if (mutex_lock_interruptible(&ap_attr_mutex))
		return -ERESTARTSYS;

	/* Do not allow apmask/aqmask if driver override is active */
	if (ap_driver_override_ctr)
		goto done;

	rc = ap_parse_bitmap_str(buf, ap_perms.aqm, AP_DOMAINS, newaqm);
	if (rc)
		goto done;
+2 −0
Original line number Diff line number Diff line
@@ -281,6 +281,8 @@ struct ap_perms {
};

extern struct ap_perms ap_perms;
extern bool ap_apmask_aqmask_in_use;
extern int ap_driver_override_ctr;
extern struct mutex ap_attr_mutex;

/*
+20 −3
Original line number Diff line number Diff line
@@ -755,13 +755,30 @@ static ssize_t driver_override_store(struct device *dev,
{
	struct ap_queue *aq = to_ap_queue(dev);
	struct ap_device *ap_dev = &aq->ap_dev;
	int rc;
	int rc = -EINVAL;
	bool old_value;

	if (mutex_lock_interruptible(&ap_attr_mutex))
		return -ERESTARTSYS;

	/* Do not allow driver override if apmask/aqmask is in use */
	if (ap_apmask_aqmask_in_use)
		goto out;

	old_value = ap_dev->driver_override ? true : false;
	rc = driver_set_override(dev, &ap_dev->driver_override, buf, count);
	if (rc)
		return rc;
		goto out;
	if (old_value && !ap_dev->driver_override)
		--ap_driver_override_ctr;
	else if (!old_value && ap_dev->driver_override)
		++ap_driver_override_ctr;

	return count;
	rc = count;

out:
	mutex_unlock(&ap_attr_mutex);
	return rc;
}

static DEVICE_ATTR_RW(driver_override);