Skip to content

Commit 8fb456b

Browse files
Jason J. HerneAlexander Gordeev
authored andcommitted
s390/vfio-ap: Add write support to sysfs attr ap_config
Allow writing a complete set of masks to ap_config. Doing so will cause the vfio-ap driver to replace the vfio-ap mediated device's matrix masks with the given set of masks. If the given state cannot be set, then no changes are made to the vfio-ap mediated device. The format of the data written to ap_config is as follows: {amask},{dmask},{cmask}\n \n is a newline character. amask, dmask, and cmask are masks identifying which adapters, domains, and control domains should be assigned to the mediated device. The format of a mask is as follows: 0xNN..NN Where NN..NN is 64 hexadecimal characters representing a 256-bit value. The leftmost (highest order) bit represents adapter/domain 0. For an example set of masks that represent your mdev's current configuration, simply cat ap_config. This attribute is intended to be used by an mdevctl callout script supporting the mdev type vfio_ap-passthrough to atomically update a vfio-ap mediated device's state. Signed-off-by: "Jason J. Herne" <jjherne@linux.ibm.com> Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com> Tested-by: Matthew Rosato <mjrosato@linux.ibm.com> Link: https://lore.kernel.org/r/20240415152555.13152-5-jjherne@linux.ibm.com Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
1 parent f3e3a40 commit 8fb456b

File tree

2 files changed

+180
-16
lines changed

2 files changed

+180
-16
lines changed

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 177 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,20 +1119,29 @@ static void vfio_ap_mdev_unlink_adapter(struct ap_matrix_mdev *matrix_mdev,
11191119
}
11201120
}
11211121

1122-
static void vfio_ap_mdev_hot_unplug_adapter(struct ap_matrix_mdev *matrix_mdev,
1123-
unsigned long apid)
1122+
static void vfio_ap_mdev_hot_unplug_adapters(struct ap_matrix_mdev *matrix_mdev,
1123+
unsigned long *apids)
11241124
{
11251125
struct vfio_ap_queue *q, *tmpq;
11261126
struct list_head qlist;
1127+
unsigned long apid;
1128+
bool apcb_update = false;
11271129

11281130
INIT_LIST_HEAD(&qlist);
1129-
vfio_ap_mdev_unlink_adapter(matrix_mdev, apid, &qlist);
11301131

1131-
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm)) {
1132-
clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
1133-
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
1132+
for_each_set_bit_inv(apid, apids, AP_DEVICES) {
1133+
vfio_ap_mdev_unlink_adapter(matrix_mdev, apid, &qlist);
1134+
1135+
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm)) {
1136+
clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
1137+
apcb_update = true;
1138+
}
11341139
}
11351140

1141+
/* Only update apcb if needed to avoid impacting guest */
1142+
if (apcb_update)
1143+
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
1144+
11361145
vfio_ap_mdev_reset_qlist(&qlist);
11371146

11381147
list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode) {
@@ -1141,6 +1150,16 @@ static void vfio_ap_mdev_hot_unplug_adapter(struct ap_matrix_mdev *matrix_mdev,
11411150
}
11421151
}
11431152

1153+
static void vfio_ap_mdev_hot_unplug_adapter(struct ap_matrix_mdev *matrix_mdev,
1154+
unsigned long apid)
1155+
{
1156+
DECLARE_BITMAP(apids, AP_DEVICES);
1157+
1158+
bitmap_zero(apids, AP_DEVICES);
1159+
set_bit_inv(apid, apids);
1160+
vfio_ap_mdev_hot_unplug_adapters(matrix_mdev, apids);
1161+
}
1162+
11441163
/**
11451164
* unassign_adapter_store - parses the APID from @buf and clears the
11461165
* corresponding bit in the mediated matrix device's APM
@@ -1301,20 +1320,29 @@ static void vfio_ap_mdev_unlink_domain(struct ap_matrix_mdev *matrix_mdev,
13011320
}
13021321
}
13031322

1304-
static void vfio_ap_mdev_hot_unplug_domain(struct ap_matrix_mdev *matrix_mdev,
1305-
unsigned long apqi)
1323+
static void vfio_ap_mdev_hot_unplug_domains(struct ap_matrix_mdev *matrix_mdev,
1324+
unsigned long *apqis)
13061325
{
13071326
struct vfio_ap_queue *q, *tmpq;
13081327
struct list_head qlist;
1328+
unsigned long apqi;
1329+
bool apcb_update = false;
13091330

13101331
INIT_LIST_HEAD(&qlist);
1311-
vfio_ap_mdev_unlink_domain(matrix_mdev, apqi, &qlist);
13121332

1313-
if (test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) {
1314-
clear_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm);
1315-
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
1333+
for_each_set_bit_inv(apqi, apqis, AP_DOMAINS) {
1334+
vfio_ap_mdev_unlink_domain(matrix_mdev, apqi, &qlist);
1335+
1336+
if (test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) {
1337+
clear_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm);
1338+
apcb_update = true;
1339+
}
13161340
}
13171341

1342+
/* Only update apcb if needed to avoid impacting guest */
1343+
if (apcb_update)
1344+
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
1345+
13181346
vfio_ap_mdev_reset_qlist(&qlist);
13191347

13201348
list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode) {
@@ -1323,6 +1351,16 @@ static void vfio_ap_mdev_hot_unplug_domain(struct ap_matrix_mdev *matrix_mdev,
13231351
}
13241352
}
13251353

1354+
static void vfio_ap_mdev_hot_unplug_domain(struct ap_matrix_mdev *matrix_mdev,
1355+
unsigned long apqi)
1356+
{
1357+
DECLARE_BITMAP(apqis, AP_DOMAINS);
1358+
1359+
bitmap_zero(apqis, AP_DEVICES);
1360+
set_bit_inv(apqi, apqis);
1361+
vfio_ap_mdev_hot_unplug_domains(matrix_mdev, apqis);
1362+
}
1363+
13261364
/**
13271365
* unassign_domain_store - parses the APQI from @buf and clears the
13281366
* corresponding bit in the mediated matrix device's AQM
@@ -1590,10 +1628,136 @@ static ssize_t ap_config_show(struct device *dev, struct device_attribute *attr,
15901628
return idx;
15911629
}
15921630

1631+
/* Number of characters needed for a complete hex mask representing the bits in .. */
1632+
#define AP_DEVICES_STRLEN (AP_DEVICES / 4 + 3)
1633+
#define AP_DOMAINS_STRLEN (AP_DOMAINS / 4 + 3)
1634+
#define AP_CONFIG_STRLEN (AP_DEVICES_STRLEN + 2 * AP_DOMAINS_STRLEN)
1635+
1636+
static int parse_bitmap(char **strbufptr, unsigned long *bitmap, int nbits)
1637+
{
1638+
char *curmask;
1639+
1640+
curmask = strsep(strbufptr, ",\n");
1641+
if (!curmask)
1642+
return -EINVAL;
1643+
1644+
bitmap_clear(bitmap, 0, nbits);
1645+
return ap_hex2bitmap(curmask, bitmap, nbits);
1646+
}
1647+
1648+
static int ap_matrix_overflow_check(struct ap_matrix_mdev *matrix_mdev)
1649+
{
1650+
unsigned long bit;
1651+
1652+
for_each_set_bit_inv(bit, matrix_mdev->matrix.apm, AP_DEVICES) {
1653+
if (bit > matrix_mdev->matrix.apm_max)
1654+
return -ENODEV;
1655+
}
1656+
1657+
for_each_set_bit_inv(bit, matrix_mdev->matrix.aqm, AP_DOMAINS) {
1658+
if (bit > matrix_mdev->matrix.aqm_max)
1659+
return -ENODEV;
1660+
}
1661+
1662+
for_each_set_bit_inv(bit, matrix_mdev->matrix.adm, AP_DOMAINS) {
1663+
if (bit > matrix_mdev->matrix.adm_max)
1664+
return -ENODEV;
1665+
}
1666+
1667+
return 0;
1668+
}
1669+
1670+
static void ap_matrix_copy(struct ap_matrix *dst, struct ap_matrix *src)
1671+
{
1672+
/* This check works around false positive gcc -Wstringop-overread */
1673+
if (!src)
1674+
return;
1675+
1676+
bitmap_copy(dst->apm, src->apm, AP_DEVICES);
1677+
bitmap_copy(dst->aqm, src->aqm, AP_DOMAINS);
1678+
bitmap_copy(dst->adm, src->adm, AP_DOMAINS);
1679+
}
1680+
15931681
static ssize_t ap_config_store(struct device *dev, struct device_attribute *attr,
15941682
const char *buf, size_t count)
15951683
{
1596-
return count;
1684+
struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
1685+
struct ap_matrix m_new, m_old, m_added, m_removed;
1686+
DECLARE_BITMAP(apm_filtered, AP_DEVICES);
1687+
unsigned long newbit;
1688+
char *newbuf, *rest;
1689+
int rc = count;
1690+
bool do_update;
1691+
1692+
newbuf = kstrndup(buf, AP_CONFIG_STRLEN, GFP_KERNEL);
1693+
if (!newbuf)
1694+
return -ENOMEM;
1695+
rest = newbuf;
1696+
1697+
mutex_lock(&ap_perms_mutex);
1698+
get_update_locks_for_mdev(matrix_mdev);
1699+
1700+
/* Save old state */
1701+
ap_matrix_copy(&m_old, &matrix_mdev->matrix);
1702+
if (parse_bitmap(&rest, m_new.apm, AP_DEVICES) ||
1703+
parse_bitmap(&rest, m_new.aqm, AP_DOMAINS) ||
1704+
parse_bitmap(&rest, m_new.adm, AP_DOMAINS)) {
1705+
rc = -EINVAL;
1706+
goto out;
1707+
}
1708+
1709+
bitmap_andnot(m_removed.apm, m_old.apm, m_new.apm, AP_DEVICES);
1710+
bitmap_andnot(m_removed.aqm, m_old.aqm, m_new.aqm, AP_DOMAINS);
1711+
bitmap_andnot(m_added.apm, m_new.apm, m_old.apm, AP_DEVICES);
1712+
bitmap_andnot(m_added.aqm, m_new.aqm, m_old.aqm, AP_DOMAINS);
1713+
1714+
/* Need new bitmaps in matrix_mdev for validation */
1715+
ap_matrix_copy(&matrix_mdev->matrix, &m_new);
1716+
1717+
/* Ensure new state is valid, else undo new state */
1718+
rc = vfio_ap_mdev_validate_masks(matrix_mdev);
1719+
if (rc) {
1720+
ap_matrix_copy(&matrix_mdev->matrix, &m_old);
1721+
goto out;
1722+
}
1723+
rc = ap_matrix_overflow_check(matrix_mdev);
1724+
if (rc) {
1725+
ap_matrix_copy(&matrix_mdev->matrix, &m_old);
1726+
goto out;
1727+
}
1728+
rc = count;
1729+
1730+
/* Need old bitmaps in matrix_mdev for unplug/unlink */
1731+
ap_matrix_copy(&matrix_mdev->matrix, &m_old);
1732+
1733+
/* Unlink removed adapters/domains */
1734+
vfio_ap_mdev_hot_unplug_adapters(matrix_mdev, m_removed.apm);
1735+
vfio_ap_mdev_hot_unplug_domains(matrix_mdev, m_removed.aqm);
1736+
1737+
/* Need new bitmaps in matrix_mdev for linking new adapters/domains */
1738+
ap_matrix_copy(&matrix_mdev->matrix, &m_new);
1739+
1740+
/* Link newly added adapters */
1741+
for_each_set_bit_inv(newbit, m_added.apm, AP_DEVICES)
1742+
vfio_ap_mdev_link_adapter(matrix_mdev, newbit);
1743+
1744+
for_each_set_bit_inv(newbit, m_added.aqm, AP_DOMAINS)
1745+
vfio_ap_mdev_link_domain(matrix_mdev, newbit);
1746+
1747+
/* filter resources not bound to vfio-ap */
1748+
do_update = vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered);
1749+
do_update |= vfio_ap_mdev_filter_cdoms(matrix_mdev);
1750+
1751+
/* Apply changes to shadow apbc if things changed */
1752+
if (do_update) {
1753+
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
1754+
reset_queues_for_apids(matrix_mdev, apm_filtered);
1755+
}
1756+
out:
1757+
release_update_locks_for_mdev(matrix_mdev);
1758+
mutex_unlock(&ap_perms_mutex);
1759+
kfree(newbuf);
1760+
return rc;
15971761
}
15981762
static DEVICE_ATTR_RW(ap_config);
15991763

drivers/s390/crypto/vfio_ap_private.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ extern struct ap_matrix_dev *matrix_dev;
7575
*/
7676
struct ap_matrix {
7777
unsigned long apm_max;
78-
DECLARE_BITMAP(apm, 256);
78+
DECLARE_BITMAP(apm, AP_DEVICES);
7979
unsigned long aqm_max;
80-
DECLARE_BITMAP(aqm, 256);
80+
DECLARE_BITMAP(aqm, AP_DOMAINS);
8181
unsigned long adm_max;
82-
DECLARE_BITMAP(adm, 256);
82+
DECLARE_BITMAP(adm, AP_DOMAINS);
8383
};
8484

8585
/**

0 commit comments

Comments
 (0)