Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Heiko Carstens: "Since Martin is on vacation you get the s390 pull request for the v4.15 merge window this time from me. Besides a lot of cleanups and bug fixes these are the most important changes: - a new regset for runtime instrumentation registers - hardware accelerated AES-GCM support for the aes_s390 module - support for the new CEX6S crypto cards - support for FORTIFY_SOURCE - addition of missing z13 and new z14 instructions to the in-kernel disassembler - generate opcode tables for the in-kernel disassembler out of a simple text file instead of having to manually maintain those tables - fast memset16, memset32 and memset64 implementations - removal of named saved segment support - hardware counter support for z14 - queued spinlocks and queued rwlocks implementations for s390 - use the stack_depth tracking feature for s390 BPF JIT - a new s390_sthyi system call which emulates the sthyi (store hypervisor information) instruction - removal of the old KVM virtio transport - an s390 specific CPU alternatives implementation which is used in the new spinlock code" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (88 commits) MAINTAINERS: add virtio-ccw.h to virtio/s390 section s390/noexec: execute kexec datamover without DAT s390: fix transactional execution control register handling s390/bpf: take advantage of stack_depth tracking s390: simplify transactional execution elf hwcap handling s390/zcrypt: Rework struct ap_qact_ap_info. s390/virtio: remove unused header file kvm_virtio.h s390: avoid undefined behaviour s390/disassembler: generate opcode tables from text file s390/disassembler: remove insn_to_mnemonic() s390/dasd: avoid calling do_gettimeofday() s390: vfio-ccw: Do not attempt to free no-op, test and tic cda. s390: remove named saved segment support s390/archrandom: Reconsider s390 arch random implementation s390/pci: do not require AIS facility s390/qdio: sanitize put_indicator s390/qdio: use atomic_cmpxchg s390/nmi: avoid using long-displacement facility s390: pass endianness info to sparse s390/decompressor: remove informational messages ...
This commit is contained in:
@@ -117,6 +117,49 @@ static inline int ap_qci(void *config)
|
||||
return reg1;
|
||||
}
|
||||
|
||||
/*
|
||||
* union ap_qact_ap_info - used together with the
|
||||
* ap_aqic() function to provide a convenient way
|
||||
* to handle the ap info needed by the qact function.
|
||||
*/
|
||||
union ap_qact_ap_info {
|
||||
unsigned long val;
|
||||
struct {
|
||||
unsigned int : 3;
|
||||
unsigned int mode : 3;
|
||||
unsigned int : 26;
|
||||
unsigned int cat : 8;
|
||||
unsigned int : 8;
|
||||
unsigned char ver[2];
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* ap_qact(): Query AP combatibility type.
|
||||
* @qid: The AP queue number
|
||||
* @apinfo: On input the info about the AP queue. On output the
|
||||
* alternate AP queue info provided by the qact function
|
||||
* in GR2 is stored in.
|
||||
*
|
||||
* Returns AP queue status. Check response_code field for failures.
|
||||
*/
|
||||
static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
|
||||
union ap_qact_ap_info *apinfo)
|
||||
{
|
||||
register unsigned long reg0 asm ("0") = qid | (5UL << 24)
|
||||
| ((ifbit & 0x01) << 22);
|
||||
register unsigned long reg1_in asm ("1") = apinfo->val;
|
||||
register struct ap_queue_status reg1_out asm ("1");
|
||||
register unsigned long reg2 asm ("2") = 0;
|
||||
|
||||
asm volatile(
|
||||
".long 0xb2af0000" /* PQAP(QACT) */
|
||||
: "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2)
|
||||
: : "cc");
|
||||
apinfo->val = reg2;
|
||||
return reg1_out;
|
||||
}
|
||||
|
||||
/**
|
||||
* ap_nqap(): Send message to adjunct processor queue.
|
||||
* @qid: The AP queue number
|
||||
|
@@ -176,6 +176,18 @@ static int ap_apft_available(void)
|
||||
return test_facility(15);
|
||||
}
|
||||
|
||||
/*
|
||||
* ap_qact_available(): Test if the PQAP(QACT) subfunction is available.
|
||||
*
|
||||
* Returns 1 if the QACT subfunction is available.
|
||||
*/
|
||||
static inline int ap_qact_available(void)
|
||||
{
|
||||
if (ap_configuration)
|
||||
return ap_configuration->qact;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ap_test_queue(): Test adjunct processor queue.
|
||||
* @qid: The AP queue number
|
||||
@@ -987,6 +999,47 @@ static int ap_select_domain(void)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks the type and returns either 0 for not
|
||||
* supported or the highest compatible type value (which may
|
||||
* include the input type value).
|
||||
*/
|
||||
static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
|
||||
{
|
||||
int comp_type = 0;
|
||||
|
||||
/* < CEX2A is not supported */
|
||||
if (rawtype < AP_DEVICE_TYPE_CEX2A)
|
||||
return 0;
|
||||
/* up to CEX6 known and fully supported */
|
||||
if (rawtype <= AP_DEVICE_TYPE_CEX6)
|
||||
return rawtype;
|
||||
/*
|
||||
* unknown new type > CEX6, check for compatibility
|
||||
* to the highest known and supported type which is
|
||||
* currently CEX6 with the help of the QACT function.
|
||||
*/
|
||||
if (ap_qact_available()) {
|
||||
struct ap_queue_status status;
|
||||
union ap_qact_ap_info apinfo = {0};
|
||||
|
||||
apinfo.mode = (func >> 26) & 0x07;
|
||||
apinfo.cat = AP_DEVICE_TYPE_CEX6;
|
||||
status = ap_qact(qid, 0, &apinfo);
|
||||
if (status.response_code == AP_RESPONSE_NORMAL
|
||||
&& apinfo.cat >= AP_DEVICE_TYPE_CEX2A
|
||||
&& apinfo.cat <= AP_DEVICE_TYPE_CEX6)
|
||||
comp_type = apinfo.cat;
|
||||
}
|
||||
if (!comp_type)
|
||||
AP_DBF(DBF_WARN, "queue=%02x.%04x unable to map type %d\n",
|
||||
AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype);
|
||||
else if (comp_type != rawtype)
|
||||
AP_DBF(DBF_INFO, "queue=%02x.%04x map type %d to %d\n",
|
||||
AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype, comp_type);
|
||||
return comp_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function to be used with bus_find_dev
|
||||
* matches for the card device with the given id
|
||||
@@ -1014,8 +1067,8 @@ static void ap_scan_bus(struct work_struct *unused)
|
||||
struct ap_card *ac;
|
||||
struct device *dev;
|
||||
ap_qid_t qid;
|
||||
int depth = 0, type = 0;
|
||||
unsigned int functions = 0;
|
||||
int comp_type, depth = 0, type = 0;
|
||||
unsigned int func = 0;
|
||||
int rc, id, dom, borked, domains, defdomdevs = 0;
|
||||
|
||||
AP_DBF(DBF_DEBUG, "ap_scan_bus running\n");
|
||||
@@ -1066,12 +1119,12 @@ static void ap_scan_bus(struct work_struct *unused)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
rc = ap_query_queue(qid, &depth, &type, &functions);
|
||||
rc = ap_query_queue(qid, &depth, &type, &func);
|
||||
if (dev) {
|
||||
spin_lock_bh(&aq->lock);
|
||||
if (rc == -ENODEV ||
|
||||
/* adapter reconfiguration */
|
||||
(ac && ac->functions != functions))
|
||||
(ac && ac->functions != func))
|
||||
aq->state = AP_STATE_BORKED;
|
||||
borked = aq->state == AP_STATE_BORKED;
|
||||
spin_unlock_bh(&aq->lock);
|
||||
@@ -1087,11 +1140,14 @@ static void ap_scan_bus(struct work_struct *unused)
|
||||
}
|
||||
if (rc)
|
||||
continue;
|
||||
/* new queue device needed */
|
||||
/* a new queue device is needed, check out comp type */
|
||||
comp_type = ap_get_compatible_type(qid, type, func);
|
||||
if (!comp_type)
|
||||
continue;
|
||||
/* maybe a card device needs to be created first */
|
||||
if (!ac) {
|
||||
/* but first create the card device */
|
||||
ac = ap_card_create(id, depth,
|
||||
type, functions);
|
||||
ac = ap_card_create(id, depth, type,
|
||||
comp_type, func);
|
||||
if (!ac)
|
||||
continue;
|
||||
ac->ap_dev.device.bus = &ap_bus_type;
|
||||
@@ -1109,7 +1165,7 @@ static void ap_scan_bus(struct work_struct *unused)
|
||||
get_device(&ac->ap_dev.device);
|
||||
}
|
||||
/* now create the new queue device */
|
||||
aq = ap_queue_create(qid, type);
|
||||
aq = ap_queue_create(qid, comp_type);
|
||||
if (!aq)
|
||||
continue;
|
||||
aq->card = ac;
|
||||
|
@@ -250,8 +250,8 @@ void ap_queue_remove(struct ap_queue *aq);
|
||||
void ap_queue_suspend(struct ap_device *ap_dev);
|
||||
void ap_queue_resume(struct ap_device *ap_dev);
|
||||
|
||||
struct ap_card *ap_card_create(int id, int queue_depth, int device_type,
|
||||
unsigned int device_functions);
|
||||
struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
|
||||
int comp_device_type, unsigned int functions);
|
||||
|
||||
int ap_module_init(void);
|
||||
void ap_module_exit(void);
|
||||
|
@@ -171,22 +171,20 @@ static void ap_card_device_release(struct device *dev)
|
||||
kfree(ac);
|
||||
}
|
||||
|
||||
struct ap_card *ap_card_create(int id, int queue_depth, int device_type,
|
||||
unsigned int functions)
|
||||
struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
|
||||
int comp_type, unsigned int functions)
|
||||
{
|
||||
struct ap_card *ac;
|
||||
|
||||
ac = kzalloc(sizeof(*ac), GFP_KERNEL);
|
||||
if (!ac)
|
||||
return NULL;
|
||||
INIT_LIST_HEAD(&ac->list);
|
||||
INIT_LIST_HEAD(&ac->queues);
|
||||
ac->ap_dev.device.release = ap_card_device_release;
|
||||
ac->ap_dev.device.type = &ap_card_type;
|
||||
ac->ap_dev.device_type = device_type;
|
||||
/* CEX6 toleration: map to CEX5 */
|
||||
if (device_type == AP_DEVICE_TYPE_CEX6)
|
||||
ac->ap_dev.device_type = AP_DEVICE_TYPE_CEX5;
|
||||
ac->raw_hwtype = device_type;
|
||||
ac->ap_dev.device_type = comp_type;
|
||||
ac->raw_hwtype = raw_type;
|
||||
ac->queue_depth = queue_depth;
|
||||
ac->functions = functions;
|
||||
ac->id = id;
|
||||
|
@@ -627,13 +627,11 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type)
|
||||
aq->ap_dev.device.release = ap_queue_device_release;
|
||||
aq->ap_dev.device.type = &ap_queue_type;
|
||||
aq->ap_dev.device_type = device_type;
|
||||
/* CEX6 toleration: map to CEX5 */
|
||||
if (device_type == AP_DEVICE_TYPE_CEX6)
|
||||
aq->ap_dev.device_type = AP_DEVICE_TYPE_CEX5;
|
||||
aq->qid = qid;
|
||||
aq->state = AP_STATE_RESET_START;
|
||||
aq->interrupt = AP_INTR_DISABLED;
|
||||
spin_lock_init(&aq->lock);
|
||||
INIT_LIST_HEAD(&aq->list);
|
||||
INIT_LIST_HEAD(&aq->pendingq);
|
||||
INIT_LIST_HEAD(&aq->requestq);
|
||||
setup_timer(&aq->timeout, ap_request_timeout, (unsigned long) aq);
|
||||
|
@@ -125,10 +125,9 @@ static int alloc_and_prep_cprbmem(size_t paramblen,
|
||||
* allocate consecutive memory for request CPRB, request param
|
||||
* block, reply CPRB and reply param block
|
||||
*/
|
||||
cprbmem = kmalloc(2 * cprbplusparamblen, GFP_KERNEL);
|
||||
cprbmem = kzalloc(2 * cprbplusparamblen, GFP_KERNEL);
|
||||
if (!cprbmem)
|
||||
return -ENOMEM;
|
||||
memset(cprbmem, 0, 2 * cprbplusparamblen);
|
||||
|
||||
preqcblk = (struct CPRBX *) cprbmem;
|
||||
prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen);
|
||||
|
@@ -76,6 +76,7 @@ struct ica_z90_status {
|
||||
#define ZCRYPT_CEX3A 8
|
||||
#define ZCRYPT_CEX4 10
|
||||
#define ZCRYPT_CEX5 11
|
||||
#define ZCRYPT_CEX6 12
|
||||
|
||||
/**
|
||||
* Large random numbers are pulled in 4096 byte chunks from the crypto cards
|
||||
|
@@ -45,6 +45,8 @@ static struct ap_device_id zcrypt_cex4_card_ids[] = {
|
||||
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
|
||||
{ .dev_type = AP_DEVICE_TYPE_CEX5,
|
||||
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
|
||||
{ .dev_type = AP_DEVICE_TYPE_CEX6,
|
||||
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
||||
@@ -55,6 +57,8 @@ static struct ap_device_id zcrypt_cex4_queue_ids[] = {
|
||||
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
|
||||
{ .dev_type = AP_DEVICE_TYPE_CEX5,
|
||||
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
|
||||
{ .dev_type = AP_DEVICE_TYPE_CEX6,
|
||||
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
||||
@@ -72,17 +76,25 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
|
||||
* MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
|
||||
*/
|
||||
static const int CEX4A_SPEED_IDX[] = {
|
||||
5, 6, 59, 20, 115, 581, 0, 0};
|
||||
14, 19, 249, 42, 228, 1458, 0, 0};
|
||||
static const int CEX5A_SPEED_IDX[] = {
|
||||
3, 3, 6, 8, 32, 218, 0, 0};
|
||||
8, 9, 20, 18, 66, 458, 0, 0};
|
||||
static const int CEX6A_SPEED_IDX[] = {
|
||||
6, 9, 20, 17, 65, 438, 0, 0};
|
||||
|
||||
static const int CEX4C_SPEED_IDX[] = {
|
||||
24, 25, 82, 41, 138, 1111, 79, 8};
|
||||
59, 69, 308, 83, 278, 2204, 209, 40};
|
||||
static const int CEX5C_SPEED_IDX[] = {
|
||||
10, 14, 23, 17, 45, 242, 63, 4};
|
||||
24, 31, 50, 37, 90, 479, 27, 10};
|
||||
static const int CEX6C_SPEED_IDX[] = {
|
||||
16, 20, 32, 27, 77, 455, 23, 9};
|
||||
|
||||
static const int CEX4P_SPEED_IDX[] = {
|
||||
142, 198, 1852, 203, 331, 1563, 0, 8};
|
||||
224, 313, 3560, 359, 605, 2827, 0, 50};
|
||||
static const int CEX5P_SPEED_IDX[] = {
|
||||
49, 67, 131, 52, 85, 287, 0, 4};
|
||||
63, 84, 156, 83, 142, 533, 0, 10};
|
||||
static const int CEX6P_SPEED_IDX[] = {
|
||||
55, 70, 121, 73, 129, 522, 0, 9};
|
||||
|
||||
struct ap_card *ac = to_ap_card(&ap_dev->device);
|
||||
struct zcrypt_card *zc;
|
||||
@@ -99,11 +111,16 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
|
||||
zc->user_space_type = ZCRYPT_CEX4;
|
||||
memcpy(zc->speed_rating, CEX4A_SPEED_IDX,
|
||||
sizeof(CEX4A_SPEED_IDX));
|
||||
} else {
|
||||
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
|
||||
zc->type_string = "CEX5A";
|
||||
zc->user_space_type = ZCRYPT_CEX5;
|
||||
memcpy(zc->speed_rating, CEX5A_SPEED_IDX,
|
||||
sizeof(CEX5A_SPEED_IDX));
|
||||
} else {
|
||||
zc->type_string = "CEX6A";
|
||||
zc->user_space_type = ZCRYPT_CEX6;
|
||||
memcpy(zc->speed_rating, CEX6A_SPEED_IDX,
|
||||
sizeof(CEX6A_SPEED_IDX));
|
||||
}
|
||||
zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
|
||||
if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
|
||||
@@ -125,7 +142,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
|
||||
zc->user_space_type = ZCRYPT_CEX3C;
|
||||
memcpy(zc->speed_rating, CEX4C_SPEED_IDX,
|
||||
sizeof(CEX4C_SPEED_IDX));
|
||||
} else {
|
||||
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
|
||||
zc->type_string = "CEX5C";
|
||||
/* wrong user space type, must be CEX5
|
||||
* just keep it for cca compatibility
|
||||
@@ -133,6 +150,14 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
|
||||
zc->user_space_type = ZCRYPT_CEX3C;
|
||||
memcpy(zc->speed_rating, CEX5C_SPEED_IDX,
|
||||
sizeof(CEX5C_SPEED_IDX));
|
||||
} else {
|
||||
zc->type_string = "CEX6C";
|
||||
/* wrong user space type, must be CEX6
|
||||
* just keep it for cca compatibility
|
||||
*/
|
||||
zc->user_space_type = ZCRYPT_CEX3C;
|
||||
memcpy(zc->speed_rating, CEX6C_SPEED_IDX,
|
||||
sizeof(CEX6C_SPEED_IDX));
|
||||
}
|
||||
zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
|
||||
zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
|
||||
@@ -143,11 +168,16 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
|
||||
zc->user_space_type = ZCRYPT_CEX4;
|
||||
memcpy(zc->speed_rating, CEX4P_SPEED_IDX,
|
||||
sizeof(CEX4P_SPEED_IDX));
|
||||
} else {
|
||||
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
|
||||
zc->type_string = "CEX5P";
|
||||
zc->user_space_type = ZCRYPT_CEX5;
|
||||
memcpy(zc->speed_rating, CEX5P_SPEED_IDX,
|
||||
sizeof(CEX5P_SPEED_IDX));
|
||||
} else {
|
||||
zc->type_string = "CEX6P";
|
||||
zc->user_space_type = ZCRYPT_CEX6;
|
||||
memcpy(zc->speed_rating, CEX6P_SPEED_IDX,
|
||||
sizeof(CEX6P_SPEED_IDX));
|
||||
}
|
||||
zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
|
||||
zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
|
||||
|
@@ -240,8 +240,7 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq,
|
||||
mod = meb2->modulus + sizeof(meb2->modulus) - mod_len;
|
||||
exp = meb2->exponent + sizeof(meb2->exponent) - mod_len;
|
||||
inp = meb2->message + sizeof(meb2->message) - mod_len;
|
||||
} else {
|
||||
/* mod_len > 256 = 4096 bit RSA Key */
|
||||
} else if (mod_len <= 512) {
|
||||
struct type50_meb3_msg *meb3 = ap_msg->message;
|
||||
memset(meb3, 0, sizeof(*meb3));
|
||||
ap_msg->length = sizeof(*meb3);
|
||||
@@ -251,7 +250,8 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq,
|
||||
mod = meb3->modulus + sizeof(meb3->modulus) - mod_len;
|
||||
exp = meb3->exponent + sizeof(meb3->exponent) - mod_len;
|
||||
inp = meb3->message + sizeof(meb3->message) - mod_len;
|
||||
}
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(mod, mex->n_modulus, mod_len) ||
|
||||
copy_from_user(exp, mex->b_key, mod_len) ||
|
||||
|
@@ -474,7 +474,8 @@ static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg,
|
||||
*fcode = (msg->hdr.function_code[0] << 8) | msg->hdr.function_code[1];
|
||||
*dom = (unsigned short *)&msg->cprbx.domain;
|
||||
|
||||
if (memcmp(function_code, "US", 2) == 0)
|
||||
if (memcmp(function_code, "US", 2) == 0
|
||||
|| memcmp(function_code, "AU", 2) == 0)
|
||||
ap_msg->special = 1;
|
||||
else
|
||||
ap_msg->special = 0;
|
||||
|
Reference in New Issue
Block a user