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: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
Harald Freudenberger 2025-11-19 16:27:38 +01:00 committed by Heiko Carstens
parent 8babcc2b6a
commit 46030379f1
3 changed files with 56 additions and 6 deletions

View File

@ -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;

View File

@ -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;
/*

View File

@ -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);