cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ap_card.c (5914B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright IBM Corp. 2016
      4 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
      5 *
      6 * Adjunct processor bus, card related code.
      7 */
      8
      9#define KMSG_COMPONENT "ap"
     10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
     11
     12#include <linux/init.h>
     13#include <linux/slab.h>
     14#include <asm/facility.h>
     15#include <asm/sclp.h>
     16
     17#include "ap_bus.h"
     18
     19/*
     20 * AP card related attributes.
     21 */
     22static ssize_t hwtype_show(struct device *dev,
     23			   struct device_attribute *attr, char *buf)
     24{
     25	struct ap_card *ac = to_ap_card(dev);
     26
     27	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->ap_dev.device_type);
     28}
     29
     30static DEVICE_ATTR_RO(hwtype);
     31
     32static ssize_t raw_hwtype_show(struct device *dev,
     33			       struct device_attribute *attr, char *buf)
     34{
     35	struct ap_card *ac = to_ap_card(dev);
     36
     37	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->raw_hwtype);
     38}
     39
     40static DEVICE_ATTR_RO(raw_hwtype);
     41
     42static ssize_t depth_show(struct device *dev, struct device_attribute *attr,
     43			  char *buf)
     44{
     45	struct ap_card *ac = to_ap_card(dev);
     46
     47	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->queue_depth);
     48}
     49
     50static DEVICE_ATTR_RO(depth);
     51
     52static ssize_t ap_functions_show(struct device *dev,
     53				 struct device_attribute *attr, char *buf)
     54{
     55	struct ap_card *ac = to_ap_card(dev);
     56
     57	return scnprintf(buf, PAGE_SIZE, "0x%08X\n", ac->functions);
     58}
     59
     60static DEVICE_ATTR_RO(ap_functions);
     61
     62static ssize_t request_count_show(struct device *dev,
     63				  struct device_attribute *attr,
     64				  char *buf)
     65{
     66	struct ap_card *ac = to_ap_card(dev);
     67	u64 req_cnt;
     68
     69	req_cnt = 0;
     70	spin_lock_bh(&ap_queues_lock);
     71	req_cnt = atomic64_read(&ac->total_request_count);
     72	spin_unlock_bh(&ap_queues_lock);
     73	return scnprintf(buf, PAGE_SIZE, "%llu\n", req_cnt);
     74}
     75
     76static ssize_t request_count_store(struct device *dev,
     77				   struct device_attribute *attr,
     78				   const char *buf, size_t count)
     79{
     80	int bkt;
     81	struct ap_queue *aq;
     82	struct ap_card *ac = to_ap_card(dev);
     83
     84	spin_lock_bh(&ap_queues_lock);
     85	hash_for_each(ap_queues, bkt, aq, hnode)
     86		if (ac == aq->card)
     87			aq->total_request_count = 0;
     88	spin_unlock_bh(&ap_queues_lock);
     89	atomic64_set(&ac->total_request_count, 0);
     90
     91	return count;
     92}
     93
     94static DEVICE_ATTR_RW(request_count);
     95
     96static ssize_t requestq_count_show(struct device *dev,
     97				   struct device_attribute *attr, char *buf)
     98{
     99	int bkt;
    100	struct ap_queue *aq;
    101	unsigned int reqq_cnt;
    102	struct ap_card *ac = to_ap_card(dev);
    103
    104	reqq_cnt = 0;
    105	spin_lock_bh(&ap_queues_lock);
    106	hash_for_each(ap_queues, bkt, aq, hnode)
    107		if (ac == aq->card)
    108			reqq_cnt += aq->requestq_count;
    109	spin_unlock_bh(&ap_queues_lock);
    110	return scnprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
    111}
    112
    113static DEVICE_ATTR_RO(requestq_count);
    114
    115static ssize_t pendingq_count_show(struct device *dev,
    116				   struct device_attribute *attr, char *buf)
    117{
    118	int bkt;
    119	struct ap_queue *aq;
    120	unsigned int penq_cnt;
    121	struct ap_card *ac = to_ap_card(dev);
    122
    123	penq_cnt = 0;
    124	spin_lock_bh(&ap_queues_lock);
    125	hash_for_each(ap_queues, bkt, aq, hnode)
    126		if (ac == aq->card)
    127			penq_cnt += aq->pendingq_count;
    128	spin_unlock_bh(&ap_queues_lock);
    129	return scnprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
    130}
    131
    132static DEVICE_ATTR_RO(pendingq_count);
    133
    134static ssize_t modalias_show(struct device *dev,
    135			     struct device_attribute *attr, char *buf)
    136{
    137	return scnprintf(buf, PAGE_SIZE, "ap:t%02X\n",
    138			 to_ap_dev(dev)->device_type);
    139}
    140
    141static DEVICE_ATTR_RO(modalias);
    142
    143static ssize_t config_show(struct device *dev,
    144			   struct device_attribute *attr, char *buf)
    145{
    146	struct ap_card *ac = to_ap_card(dev);
    147
    148	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->config ? 1 : 0);
    149}
    150
    151static ssize_t config_store(struct device *dev,
    152			    struct device_attribute *attr,
    153			    const char *buf, size_t count)
    154{
    155	int rc = 0, cfg;
    156	struct ap_card *ac = to_ap_card(dev);
    157
    158	if (sscanf(buf, "%d\n", &cfg) != 1 || cfg < 0 || cfg > 1)
    159		return -EINVAL;
    160
    161	if (cfg && !ac->config)
    162		rc = sclp_ap_configure(ac->id);
    163	else if (!cfg && ac->config)
    164		rc = sclp_ap_deconfigure(ac->id);
    165	if (rc)
    166		return rc;
    167
    168	ac->config = cfg ? true : false;
    169
    170	ap_send_config_uevent(&ac->ap_dev, ac->config);
    171
    172	return count;
    173}
    174
    175static DEVICE_ATTR_RW(config);
    176
    177static ssize_t chkstop_show(struct device *dev,
    178			    struct device_attribute *attr, char *buf)
    179{
    180	struct ap_card *ac = to_ap_card(dev);
    181
    182	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->chkstop ? 1 : 0);
    183}
    184
    185static DEVICE_ATTR_RO(chkstop);
    186
    187static ssize_t max_msg_size_show(struct device *dev,
    188				 struct device_attribute *attr, char *buf)
    189{
    190	struct ap_card *ac = to_ap_card(dev);
    191
    192	return scnprintf(buf, PAGE_SIZE, "%u\n", ac->maxmsgsize);
    193}
    194
    195static DEVICE_ATTR_RO(max_msg_size);
    196
    197static struct attribute *ap_card_dev_attrs[] = {
    198	&dev_attr_hwtype.attr,
    199	&dev_attr_raw_hwtype.attr,
    200	&dev_attr_depth.attr,
    201	&dev_attr_ap_functions.attr,
    202	&dev_attr_request_count.attr,
    203	&dev_attr_requestq_count.attr,
    204	&dev_attr_pendingq_count.attr,
    205	&dev_attr_modalias.attr,
    206	&dev_attr_config.attr,
    207	&dev_attr_chkstop.attr,
    208	&dev_attr_max_msg_size.attr,
    209	NULL
    210};
    211
    212static struct attribute_group ap_card_dev_attr_group = {
    213	.attrs = ap_card_dev_attrs
    214};
    215
    216static const struct attribute_group *ap_card_dev_attr_groups[] = {
    217	&ap_card_dev_attr_group,
    218	NULL
    219};
    220
    221static struct device_type ap_card_type = {
    222	.name = "ap_card",
    223	.groups = ap_card_dev_attr_groups,
    224};
    225
    226static void ap_card_device_release(struct device *dev)
    227{
    228	struct ap_card *ac = to_ap_card(dev);
    229
    230	kfree(ac);
    231}
    232
    233struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
    234			       int comp_type, unsigned int functions, int ml)
    235{
    236	struct ap_card *ac;
    237
    238	ac = kzalloc(sizeof(*ac), GFP_KERNEL);
    239	if (!ac)
    240		return NULL;
    241	ac->ap_dev.device.release = ap_card_device_release;
    242	ac->ap_dev.device.type = &ap_card_type;
    243	ac->ap_dev.device_type = comp_type;
    244	ac->raw_hwtype = raw_type;
    245	ac->queue_depth = queue_depth;
    246	ac->functions = functions;
    247	ac->id = id;
    248	ac->maxmsgsize = ml > 0 ?
    249		ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;
    250
    251	return ac;
    252}