Commit 985214af authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik

s390/zcrypt: CEX8S exploitation support

This patch adds CEX8 exploitation support for the AP bus code,
the zcrypt device driver zoo and the vfio device driver.
Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarJürgen Christ <jchrist@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent d64e5e91
...@@ -288,7 +288,7 @@ struct zcrypt_device_matrix_ext { ...@@ -288,7 +288,7 @@ struct zcrypt_device_matrix_ext {
* 0x08: CEX3A * 0x08: CEX3A
* 0x0a: CEX4 * 0x0a: CEX4
* 0x0b: CEX5 * 0x0b: CEX5
* 0x0c: CEX6 and CEX7 * 0x0c: CEX6, CEX7 or CEX8
* 0x0d: device is disabled * 0x0d: device is disabled
* *
* ZCRYPT_QDEPTH_MASK * ZCRYPT_QDEPTH_MASK
......
...@@ -1589,24 +1589,24 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func) ...@@ -1589,24 +1589,24 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
AP_QID_QUEUE(qid), rawtype); AP_QID_QUEUE(qid), rawtype);
return 0; return 0;
} }
/* up to CEX7 known and fully supported */ /* up to CEX8 known and fully supported */
if (rawtype <= AP_DEVICE_TYPE_CEX7) if (rawtype <= AP_DEVICE_TYPE_CEX8)
return rawtype; return rawtype;
/* /*
* unknown new type > CEX7, check for compatibility * unknown new type > CEX8, check for compatibility
* to the highest known and supported type which is * to the highest known and supported type which is
* currently CEX7 with the help of the QACT function. * currently CEX8 with the help of the QACT function.
*/ */
if (ap_qact_available()) { if (ap_qact_available()) {
struct ap_queue_status status; struct ap_queue_status status;
union ap_qact_ap_info apinfo = {0}; union ap_qact_ap_info apinfo = {0};
apinfo.mode = (func >> 26) & 0x07; apinfo.mode = (func >> 26) & 0x07;
apinfo.cat = AP_DEVICE_TYPE_CEX7; apinfo.cat = AP_DEVICE_TYPE_CEX8;
status = ap_qact(qid, 0, &apinfo); status = ap_qact(qid, 0, &apinfo);
if (status.response_code == AP_RESPONSE_NORMAL if (status.response_code == AP_RESPONSE_NORMAL
&& apinfo.cat >= AP_DEVICE_TYPE_CEX2A && apinfo.cat >= AP_DEVICE_TYPE_CEX2A
&& apinfo.cat <= AP_DEVICE_TYPE_CEX7) && apinfo.cat <= AP_DEVICE_TYPE_CEX8)
comp_type = apinfo.cat; comp_type = apinfo.cat;
} }
if (!comp_type) if (!comp_type)
......
...@@ -70,6 +70,7 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) ...@@ -70,6 +70,7 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
#define AP_DEVICE_TYPE_CEX5 11 #define AP_DEVICE_TYPE_CEX5 11
#define AP_DEVICE_TYPE_CEX6 12 #define AP_DEVICE_TYPE_CEX6 12
#define AP_DEVICE_TYPE_CEX7 13 #define AP_DEVICE_TYPE_CEX7 13
#define AP_DEVICE_TYPE_CEX8 14
/* /*
* Known function facilities * Known function facilities
......
...@@ -41,6 +41,8 @@ static struct ap_device_id ap_queue_ids[] = { ...@@ -41,6 +41,8 @@ static struct ap_device_id ap_queue_ids[] = {
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX7, { .dev_type = AP_DEVICE_TYPE_CEX7,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX8,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ /* end of sibling */ }, { /* end of sibling */ },
}; };
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright IBM Corp. 2012, 2019 * Copyright IBM Corp. 2012, 2022
* Author(s): Holger Dengler <hd@linux.vnet.ibm.com> * Author(s): Holger Dengler <hd@linux.vnet.ibm.com>
*/ */
...@@ -36,8 +36,8 @@ ...@@ -36,8 +36,8 @@
#define CEX4_CLEANUP_TIME (900*HZ) #define CEX4_CLEANUP_TIME (900*HZ)
MODULE_AUTHOR("IBM Corporation"); MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("CEX4/CEX5/CEX6/CEX7 Cryptographic Card device driver, " \ MODULE_DESCRIPTION("CEX[45678] Cryptographic Card device driver, " \
"Copyright IBM Corp. 2019"); "Copyright IBM Corp. 2022");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct ap_device_id zcrypt_cex4_card_ids[] = { static struct ap_device_id zcrypt_cex4_card_ids[] = {
...@@ -49,6 +49,8 @@ static struct ap_device_id zcrypt_cex4_card_ids[] = { ...@@ -49,6 +49,8 @@ static struct ap_device_id zcrypt_cex4_card_ids[] = {
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX7, { .dev_type = AP_DEVICE_TYPE_CEX7,
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX8,
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
{ /* end of list */ }, { /* end of list */ },
}; };
...@@ -63,6 +65,8 @@ static struct ap_device_id zcrypt_cex4_queue_ids[] = { ...@@ -63,6 +65,8 @@ static struct ap_device_id zcrypt_cex4_queue_ids[] = {
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX7, { .dev_type = AP_DEVICE_TYPE_CEX7,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX8,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ /* end of list */ }, { /* end of list */ },
}; };
...@@ -395,7 +399,7 @@ static const struct attribute_group ep11_queue_attr_grp = { ...@@ -395,7 +399,7 @@ static const struct attribute_group ep11_queue_attr_grp = {
}; };
/* /*
* Probe function for CEX4/CEX5/CEX6/CEX7 card device. It always * Probe function for CEX[45678] card device. It always
* accepts the AP device since the bus_match already checked * accepts the AP device since the bus_match already checked
* the hardware type. * the hardware type.
* @ap_dev: pointer to the AP device. * @ap_dev: pointer to the AP device.
...@@ -414,6 +418,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -414,6 +418,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
6, 9, 20, 17, 65, 438, 0, 0}; 6, 9, 20, 17, 65, 438, 0, 0};
static const int CEX7A_SPEED_IDX[NUM_OPS] = { static const int CEX7A_SPEED_IDX[NUM_OPS] = {
6, 8, 17, 15, 54, 362, 0, 0}; 6, 8, 17, 15, 54, 362, 0, 0};
static const int CEX8A_SPEED_IDX[NUM_OPS] = {
6, 8, 17, 15, 54, 362, 0, 0};
static const int CEX4C_SPEED_IDX[NUM_OPS] = { static const int CEX4C_SPEED_IDX[NUM_OPS] = {
59, 69, 308, 83, 278, 2204, 209, 40}; 59, 69, 308, 83, 278, 2204, 209, 40};
...@@ -423,6 +429,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -423,6 +429,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
16, 20, 32, 27, 77, 455, 24, 9}; 16, 20, 32, 27, 77, 455, 24, 9};
static const int CEX7C_SPEED_IDX[NUM_OPS] = { static const int CEX7C_SPEED_IDX[NUM_OPS] = {
14, 16, 26, 23, 64, 376, 23, 8}; 14, 16, 26, 23, 64, 376, 23, 8};
static const int CEX8C_SPEED_IDX[NUM_OPS] = {
14, 16, 26, 23, 64, 376, 23, 8};
static const int CEX4P_SPEED_IDX[NUM_OPS] = { static const int CEX4P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 50}; 0, 0, 0, 0, 0, 0, 0, 50};
...@@ -432,6 +440,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -432,6 +440,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
0, 0, 0, 0, 0, 0, 0, 9}; 0, 0, 0, 0, 0, 0, 0, 9};
static const int CEX7P_SPEED_IDX[NUM_OPS] = { static const int CEX7P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 8}; 0, 0, 0, 0, 0, 0, 0, 8};
static const int CEX8P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 8};
struct ap_card *ac = to_ap_card(&ap_dev->device); struct ap_card *ac = to_ap_card(&ap_dev->device);
struct zcrypt_card *zc; struct zcrypt_card *zc;
...@@ -455,13 +465,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -455,13 +465,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->type_string = "CEX6A"; zc->type_string = "CEX6A";
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX6A_SPEED_IDX; zc->speed_rating = CEX6A_SPEED_IDX;
} else { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
zc->type_string = "CEX7A"; zc->type_string = "CEX7A";
zc->speed_rating = CEX7A_SPEED_IDX;
/* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl.
*/
zc->user_space_type = ZCRYPT_CEX6;
} else {
zc->type_string = "CEX8A";
zc->speed_rating = CEX8A_SPEED_IDX;
/* wrong user space type, just for compatibility /* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl. * with the ZCRYPT_STATUS_MASK ioctl.
*/ */
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX7A_SPEED_IDX;
} }
zc->min_mod_size = CEX4A_MIN_MOD_SIZE; zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) && if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
...@@ -477,32 +494,39 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -477,32 +494,39 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
} else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { } else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) { if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4C"; zc->type_string = "CEX4C";
/* wrong user space type, must be CEX4 zc->speed_rating = CEX4C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX4C_SPEED_IDX;
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
zc->type_string = "CEX5C"; zc->type_string = "CEX5C";
/* wrong user space type, must be CEX5 zc->speed_rating = CEX5C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX5C_SPEED_IDX;
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
zc->type_string = "CEX6C"; zc->type_string = "CEX6C";
/* wrong user space type, must be CEX6 zc->speed_rating = CEX6C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX6C_SPEED_IDX; } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
} else {
zc->type_string = "CEX7C"; zc->type_string = "CEX7C";
/* wrong user space type, must be CEX7 zc->speed_rating = CEX7C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility
*/
zc->user_space_type = ZCRYPT_CEX3C;
} else {
zc->type_string = "CEX8C";
zc->speed_rating = CEX8C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility * just keep it for cca compatibility
*/ */
zc->user_space_type = ZCRYPT_CEX3C; zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX7C_SPEED_IDX;
} }
zc->min_mod_size = CEX4C_MIN_MOD_SIZE; zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE; zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
...@@ -520,13 +544,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -520,13 +544,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->type_string = "CEX6P"; zc->type_string = "CEX6P";
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX6P_SPEED_IDX; zc->speed_rating = CEX6P_SPEED_IDX;
} else { } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
zc->type_string = "CEX7P"; zc->type_string = "CEX7P";
zc->speed_rating = CEX7P_SPEED_IDX;
/* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl.
*/
zc->user_space_type = ZCRYPT_CEX6;
} else {
zc->type_string = "CEX8P";
zc->speed_rating = CEX8P_SPEED_IDX;
/* wrong user space type, just for compatibility /* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl. * with the ZCRYPT_STATUS_MASK ioctl.
*/ */
zc->user_space_type = ZCRYPT_CEX6; zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX7P_SPEED_IDX;
} }
zc->min_mod_size = CEX4C_MIN_MOD_SIZE; zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE; zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
...@@ -563,7 +594,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) ...@@ -563,7 +594,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
} }
/* /*
* This is called to remove the CEX4/CEX5/CEX6/CEX7 card driver * This is called to remove the CEX[45678] card driver
* information if an AP card device is removed. * information if an AP card device is removed.
*/ */
static void zcrypt_cex4_card_remove(struct ap_device *ap_dev) static void zcrypt_cex4_card_remove(struct ap_device *ap_dev)
...@@ -587,7 +618,7 @@ static struct ap_driver zcrypt_cex4_card_driver = { ...@@ -587,7 +618,7 @@ static struct ap_driver zcrypt_cex4_card_driver = {
}; };
/* /*
* Probe function for CEX4/CEX5/CEX6/CEX7 queue device. It always * Probe function for CEX[45678] queue device. It always
* accepts the AP device since the bus_match already checked * accepts the AP device since the bus_match already checked
* the hardware type. * the hardware type.
* @ap_dev: pointer to the AP device. * @ap_dev: pointer to the AP device.
...@@ -653,7 +684,7 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev) ...@@ -653,7 +684,7 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
} }
/* /*
* This is called to remove the CEX4/CEX5/CEX6/CEX7 queue driver * This is called to remove the CEX[45678] queue driver
* information if an AP queue device is removed. * information if an AP queue device is removed.
*/ */
static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev) static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment