Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Intel Software Defined Silicon driver
0004  *
0005  * Copyright (c) 2022, Intel Corporation.
0006  * All Rights Reserved.
0007  *
0008  * Author: "David E. Box" <david.e.box@linux.intel.com>
0009  */
0010 
0011 #include <linux/auxiliary_bus.h>
0012 #include <linux/bits.h>
0013 #include <linux/bitfield.h>
0014 #include <linux/device.h>
0015 #include <linux/iopoll.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/pci.h>
0019 #include <linux/slab.h>
0020 #include <linux/sysfs.h>
0021 #include <linux/types.h>
0022 #include <linux/uaccess.h>
0023 
0024 #include "vsec.h"
0025 
0026 #define ACCESS_TYPE_BARID       2
0027 #define ACCESS_TYPE_LOCAL       3
0028 
0029 #define SDSI_MIN_SIZE_DWORDS        276
0030 #define SDSI_SIZE_CONTROL       8
0031 #define SDSI_SIZE_MAILBOX       1024
0032 #define SDSI_SIZE_REGS          72
0033 #define SDSI_SIZE_CMD           sizeof(u64)
0034 
0035 /*
0036  * Write messages are currently up to the size of the mailbox
0037  * while read messages are up to 4 times the size of the
0038  * mailbox, sent in packets
0039  */
0040 #define SDSI_SIZE_WRITE_MSG     SDSI_SIZE_MAILBOX
0041 #define SDSI_SIZE_READ_MSG      (SDSI_SIZE_MAILBOX * 4)
0042 
0043 #define SDSI_ENABLED_FEATURES_OFFSET    16
0044 #define SDSI_ENABLED            BIT(3)
0045 #define SDSI_SOCKET_ID_OFFSET       64
0046 #define SDSI_SOCKET_ID          GENMASK(3, 0)
0047 
0048 #define SDSI_MBOX_CMD_SUCCESS       0x40
0049 #define SDSI_MBOX_CMD_TIMEOUT       0x80
0050 
0051 #define MBOX_TIMEOUT_US         2000
0052 #define MBOX_TIMEOUT_ACQUIRE_US     1000
0053 #define MBOX_POLLING_PERIOD_US      100
0054 #define MBOX_ACQUIRE_NUM_RETRIES    5
0055 #define MBOX_ACQUIRE_RETRY_DELAY_MS 500
0056 #define MBOX_MAX_PACKETS        4
0057 
0058 #define MBOX_OWNER_NONE         0x00
0059 #define MBOX_OWNER_INBAND       0x01
0060 
0061 #define CTRL_RUN_BUSY           BIT(0)
0062 #define CTRL_READ_WRITE         BIT(1)
0063 #define CTRL_SOM            BIT(2)
0064 #define CTRL_EOM            BIT(3)
0065 #define CTRL_OWNER          GENMASK(5, 4)
0066 #define CTRL_COMPLETE           BIT(6)
0067 #define CTRL_READY          BIT(7)
0068 #define CTRL_STATUS         GENMASK(15, 8)
0069 #define CTRL_PACKET_SIZE        GENMASK(31, 16)
0070 #define CTRL_MSG_SIZE           GENMASK(63, 48)
0071 
0072 #define DISC_TABLE_SIZE         12
0073 #define DT_ACCESS_TYPE          GENMASK(3, 0)
0074 #define DT_SIZE             GENMASK(27, 12)
0075 #define DT_TBIR             GENMASK(2, 0)
0076 #define DT_OFFSET(v)            ((v) & GENMASK(31, 3))
0077 
0078 enum sdsi_command {
0079     SDSI_CMD_PROVISION_AKC      = 0x04,
0080     SDSI_CMD_PROVISION_CAP      = 0x08,
0081     SDSI_CMD_READ_STATE     = 0x10,
0082 };
0083 
0084 struct sdsi_mbox_info {
0085     u64 *payload;
0086     void    *buffer;
0087     int size;
0088 };
0089 
0090 struct disc_table {
0091     u32 access_info;
0092     u32 guid;
0093     u32 offset;
0094 };
0095 
0096 struct sdsi_priv {
0097     struct mutex        mb_lock;    /* Mailbox access lock */
0098     struct device       *dev;
0099     void __iomem        *control_addr;
0100     void __iomem        *mbox_addr;
0101     void __iomem        *regs_addr;
0102     u32         guid;
0103     bool            sdsi_enabled;
0104 };
0105 
0106 /* SDSi mailbox operations must be performed using 64bit mov instructions */
0107 static __always_inline void
0108 sdsi_memcpy64_toio(u64 __iomem *to, const u64 *from, size_t count_bytes)
0109 {
0110     size_t count = count_bytes / sizeof(*to);
0111     int i;
0112 
0113     for (i = 0; i < count; i++)
0114         writeq(from[i], &to[i]);
0115 }
0116 
0117 static __always_inline void
0118 sdsi_memcpy64_fromio(u64 *to, const u64 __iomem *from, size_t count_bytes)
0119 {
0120     size_t count = count_bytes / sizeof(*to);
0121     int i;
0122 
0123     for (i = 0; i < count; i++)
0124         to[i] = readq(&from[i]);
0125 }
0126 
0127 static inline void sdsi_complete_transaction(struct sdsi_priv *priv)
0128 {
0129     u64 control = FIELD_PREP(CTRL_COMPLETE, 1);
0130 
0131     lockdep_assert_held(&priv->mb_lock);
0132     writeq(control, priv->control_addr);
0133 }
0134 
0135 static int sdsi_status_to_errno(u32 status)
0136 {
0137     switch (status) {
0138     case SDSI_MBOX_CMD_SUCCESS:
0139         return 0;
0140     case SDSI_MBOX_CMD_TIMEOUT:
0141         return -ETIMEDOUT;
0142     default:
0143         return -EIO;
0144     }
0145 }
0146 
0147 static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
0148                   size_t *data_size)
0149 {
0150     struct device *dev = priv->dev;
0151     u32 total, loop, eom, status, message_size;
0152     u64 control;
0153     int ret;
0154 
0155     lockdep_assert_held(&priv->mb_lock);
0156 
0157     /* Format and send the read command */
0158     control = FIELD_PREP(CTRL_EOM, 1) |
0159           FIELD_PREP(CTRL_SOM, 1) |
0160           FIELD_PREP(CTRL_RUN_BUSY, 1) |
0161           FIELD_PREP(CTRL_PACKET_SIZE, info->size);
0162     writeq(control, priv->control_addr);
0163 
0164     /* For reads, data sizes that are larger than the mailbox size are read in packets. */
0165     total = 0;
0166     loop = 0;
0167     do {
0168         void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop);
0169         u32 packet_size;
0170 
0171         /* Poll on ready bit */
0172         ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
0173                      MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
0174         if (ret)
0175             break;
0176 
0177         eom = FIELD_GET(CTRL_EOM, control);
0178         status = FIELD_GET(CTRL_STATUS, control);
0179         packet_size = FIELD_GET(CTRL_PACKET_SIZE, control);
0180         message_size = FIELD_GET(CTRL_MSG_SIZE, control);
0181 
0182         ret = sdsi_status_to_errno(status);
0183         if (ret)
0184             break;
0185 
0186         /* Only the last packet can be less than the mailbox size. */
0187         if (!eom && packet_size != SDSI_SIZE_MAILBOX) {
0188             dev_err(dev, "Invalid packet size\n");
0189             ret = -EPROTO;
0190             break;
0191         }
0192 
0193         if (packet_size > SDSI_SIZE_MAILBOX) {
0194             dev_err(dev, "Packet size too large\n");
0195             ret = -EPROTO;
0196             break;
0197         }
0198 
0199         sdsi_memcpy64_fromio(buf, priv->mbox_addr, round_up(packet_size, SDSI_SIZE_CMD));
0200 
0201         total += packet_size;
0202 
0203         sdsi_complete_transaction(priv);
0204     } while (!eom && ++loop < MBOX_MAX_PACKETS);
0205 
0206     if (ret) {
0207         sdsi_complete_transaction(priv);
0208         return ret;
0209     }
0210 
0211     if (!eom) {
0212         dev_err(dev, "Exceeded read attempts\n");
0213         return -EPROTO;
0214     }
0215 
0216     /* Message size check is only valid for multi-packet transfers */
0217     if (loop && total != message_size)
0218         dev_warn(dev, "Read count %u differs from expected count %u\n",
0219              total, message_size);
0220 
0221     *data_size = total;
0222 
0223     return 0;
0224 }
0225 
0226 static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
0227 {
0228     u64 control;
0229     u32 status;
0230     int ret;
0231 
0232     lockdep_assert_held(&priv->mb_lock);
0233 
0234     /* Write rest of the payload */
0235     sdsi_memcpy64_toio(priv->mbox_addr + SDSI_SIZE_CMD, info->payload + 1,
0236                info->size - SDSI_SIZE_CMD);
0237 
0238     /* Format and send the write command */
0239     control = FIELD_PREP(CTRL_EOM, 1) |
0240           FIELD_PREP(CTRL_SOM, 1) |
0241           FIELD_PREP(CTRL_RUN_BUSY, 1) |
0242           FIELD_PREP(CTRL_READ_WRITE, 1) |
0243           FIELD_PREP(CTRL_PACKET_SIZE, info->size);
0244     writeq(control, priv->control_addr);
0245 
0246     /* Poll on ready bit */
0247     ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
0248                  MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
0249 
0250     if (ret)
0251         goto release_mbox;
0252 
0253     status = FIELD_GET(CTRL_STATUS, control);
0254     ret = sdsi_status_to_errno(status);
0255 
0256 release_mbox:
0257     sdsi_complete_transaction(priv);
0258 
0259     return ret;
0260 }
0261 
0262 static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
0263 {
0264     u64 control;
0265     u32 owner;
0266     int ret, retries = 0;
0267 
0268     lockdep_assert_held(&priv->mb_lock);
0269 
0270     /* Check mailbox is available */
0271     control = readq(priv->control_addr);
0272     owner = FIELD_GET(CTRL_OWNER, control);
0273     if (owner != MBOX_OWNER_NONE)
0274         return -EBUSY;
0275 
0276     /*
0277      * If there has been no recent transaction and no one owns the mailbox,
0278      * we should acquire it in under 1ms. However, if we've accessed it
0279      * recently it may take up to 2.1 seconds to acquire it again.
0280      */
0281     do {
0282         /* Write first qword of payload */
0283         writeq(info->payload[0], priv->mbox_addr);
0284 
0285         /* Check for ownership */
0286         ret = readq_poll_timeout(priv->control_addr, control,
0287             FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_INBAND,
0288             MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
0289 
0290         if (FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_NONE &&
0291             retries++ < MBOX_ACQUIRE_NUM_RETRIES) {
0292             msleep(MBOX_ACQUIRE_RETRY_DELAY_MS);
0293             continue;
0294         }
0295 
0296         /* Either we got it or someone else did. */
0297         break;
0298     } while (true);
0299 
0300     return ret;
0301 }
0302 
0303 static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
0304 {
0305     int ret;
0306 
0307     lockdep_assert_held(&priv->mb_lock);
0308 
0309     ret = sdsi_mbox_acquire(priv, info);
0310     if (ret)
0311         return ret;
0312 
0313     return sdsi_mbox_cmd_write(priv, info);
0314 }
0315 
0316 static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, size_t *data_size)
0317 {
0318     int ret;
0319 
0320     lockdep_assert_held(&priv->mb_lock);
0321 
0322     ret = sdsi_mbox_acquire(priv, info);
0323     if (ret)
0324         return ret;
0325 
0326     return sdsi_mbox_cmd_read(priv, info, data_size);
0327 }
0328 
0329 static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
0330                   enum sdsi_command command)
0331 {
0332     struct sdsi_mbox_info info;
0333     int ret;
0334 
0335     if (!priv->sdsi_enabled)
0336         return -EPERM;
0337 
0338     if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
0339         return -EOVERFLOW;
0340 
0341     /* Qword aligned message + command qword */
0342     info.size = round_up(count, SDSI_SIZE_CMD) + SDSI_SIZE_CMD;
0343 
0344     info.payload = kzalloc(info.size, GFP_KERNEL);
0345     if (!info.payload)
0346         return -ENOMEM;
0347 
0348     /* Copy message to payload buffer */
0349     memcpy(info.payload, buf, count);
0350 
0351     /* Command is last qword of payload buffer */
0352     info.payload[(info.size - SDSI_SIZE_CMD) / SDSI_SIZE_CMD] = command;
0353 
0354     ret = mutex_lock_interruptible(&priv->mb_lock);
0355     if (ret)
0356         goto free_payload;
0357     ret = sdsi_mbox_write(priv, &info);
0358     mutex_unlock(&priv->mb_lock);
0359 
0360 free_payload:
0361     kfree(info.payload);
0362 
0363     if (ret)
0364         return ret;
0365 
0366     return count;
0367 }
0368 
0369 static ssize_t provision_akc_write(struct file *filp, struct kobject *kobj,
0370                    struct bin_attribute *attr, char *buf, loff_t off,
0371                    size_t count)
0372 {
0373     struct device *dev = kobj_to_dev(kobj);
0374     struct sdsi_priv *priv = dev_get_drvdata(dev);
0375 
0376     if (off)
0377         return -ESPIPE;
0378 
0379     return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_AKC);
0380 }
0381 static BIN_ATTR_WO(provision_akc, SDSI_SIZE_WRITE_MSG);
0382 
0383 static ssize_t provision_cap_write(struct file *filp, struct kobject *kobj,
0384                    struct bin_attribute *attr, char *buf, loff_t off,
0385                    size_t count)
0386 {
0387     struct device *dev = kobj_to_dev(kobj);
0388     struct sdsi_priv *priv = dev_get_drvdata(dev);
0389 
0390     if (off)
0391         return -ESPIPE;
0392 
0393     return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_CAP);
0394 }
0395 static BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG);
0396 
0397 static long state_certificate_read(struct file *filp, struct kobject *kobj,
0398                    struct bin_attribute *attr, char *buf, loff_t off,
0399                    size_t count)
0400 {
0401     struct device *dev = kobj_to_dev(kobj);
0402     struct sdsi_priv *priv = dev_get_drvdata(dev);
0403     u64 command = SDSI_CMD_READ_STATE;
0404     struct sdsi_mbox_info info;
0405     size_t size;
0406     int ret;
0407 
0408     if (!priv->sdsi_enabled)
0409         return -EPERM;
0410 
0411     if (off)
0412         return 0;
0413 
0414     /* Buffer for return data */
0415     info.buffer = kmalloc(SDSI_SIZE_READ_MSG, GFP_KERNEL);
0416     if (!info.buffer)
0417         return -ENOMEM;
0418 
0419     info.payload = &command;
0420     info.size = sizeof(command);
0421 
0422     ret = mutex_lock_interruptible(&priv->mb_lock);
0423     if (ret)
0424         goto free_buffer;
0425     ret = sdsi_mbox_read(priv, &info, &size);
0426     mutex_unlock(&priv->mb_lock);
0427     if (ret < 0)
0428         goto free_buffer;
0429 
0430     if (size > count)
0431         size = count;
0432 
0433     memcpy(buf, info.buffer, size);
0434 
0435 free_buffer:
0436     kfree(info.buffer);
0437 
0438     if (ret)
0439         return ret;
0440 
0441     return size;
0442 }
0443 static BIN_ATTR(state_certificate, 0400, state_certificate_read, NULL, SDSI_SIZE_READ_MSG);
0444 
0445 static ssize_t registers_read(struct file *filp, struct kobject *kobj,
0446                   struct bin_attribute *attr, char *buf, loff_t off,
0447                   size_t count)
0448 {
0449     struct device *dev = kobj_to_dev(kobj);
0450     struct sdsi_priv *priv = dev_get_drvdata(dev);
0451     void __iomem *addr = priv->regs_addr;
0452 
0453     memcpy_fromio(buf, addr + off, count);
0454 
0455     return count;
0456 }
0457 static BIN_ATTR(registers, 0400, registers_read, NULL, SDSI_SIZE_REGS);
0458 
0459 static struct bin_attribute *sdsi_bin_attrs[] = {
0460     &bin_attr_registers,
0461     &bin_attr_state_certificate,
0462     &bin_attr_provision_akc,
0463     &bin_attr_provision_cap,
0464     NULL
0465 };
0466 
0467 static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf)
0468 {
0469     struct sdsi_priv *priv = dev_get_drvdata(dev);
0470 
0471     return sysfs_emit(buf, "0x%x\n", priv->guid);
0472 }
0473 static DEVICE_ATTR_RO(guid);
0474 
0475 static struct attribute *sdsi_attrs[] = {
0476     &dev_attr_guid.attr,
0477     NULL
0478 };
0479 
0480 static const struct attribute_group sdsi_group = {
0481     .attrs = sdsi_attrs,
0482     .bin_attrs = sdsi_bin_attrs,
0483 };
0484 __ATTRIBUTE_GROUPS(sdsi);
0485 
0486 static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent,
0487                    struct disc_table *disc_table, struct resource *disc_res)
0488 {
0489     u32 access_type = FIELD_GET(DT_ACCESS_TYPE, disc_table->access_info);
0490     u32 size = FIELD_GET(DT_SIZE, disc_table->access_info);
0491     u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset);
0492     u32 offset = DT_OFFSET(disc_table->offset);
0493     u32 features_offset;
0494     struct resource res = {};
0495 
0496     /* Starting location of SDSi MMIO region based on access type */
0497     switch (access_type) {
0498     case ACCESS_TYPE_LOCAL:
0499         if (tbir) {
0500             dev_err(priv->dev, "Unsupported BAR index %u for access type %u\n",
0501                 tbir, access_type);
0502             return -EINVAL;
0503         }
0504 
0505         /*
0506          * For access_type LOCAL, the base address is as follows:
0507          * base address = end of discovery region + base offset + 1
0508          */
0509         res.start = disc_res->end + offset + 1;
0510         break;
0511 
0512     case ACCESS_TYPE_BARID:
0513         res.start = pci_resource_start(parent, tbir) + offset;
0514         break;
0515 
0516     default:
0517         dev_err(priv->dev, "Unrecognized access_type %u\n", access_type);
0518         return -EINVAL;
0519     }
0520 
0521     res.end = res.start + size * sizeof(u32) - 1;
0522     res.flags = IORESOURCE_MEM;
0523 
0524     priv->control_addr = devm_ioremap_resource(priv->dev, &res);
0525     if (IS_ERR(priv->control_addr))
0526         return PTR_ERR(priv->control_addr);
0527 
0528     priv->mbox_addr = priv->control_addr + SDSI_SIZE_CONTROL;
0529     priv->regs_addr = priv->mbox_addr + SDSI_SIZE_MAILBOX;
0530 
0531     features_offset = readq(priv->regs_addr + SDSI_ENABLED_FEATURES_OFFSET);
0532     priv->sdsi_enabled = !!(features_offset & SDSI_ENABLED);
0533 
0534     return 0;
0535 }
0536 
0537 static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
0538 {
0539     struct intel_vsec_device *intel_cap_dev = auxdev_to_ivdev(auxdev);
0540     struct disc_table disc_table;
0541     struct resource *disc_res;
0542     void __iomem *disc_addr;
0543     struct sdsi_priv *priv;
0544     int ret;
0545 
0546     priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
0547     if (!priv)
0548         return -ENOMEM;
0549 
0550     priv->dev = &auxdev->dev;
0551     mutex_init(&priv->mb_lock);
0552     auxiliary_set_drvdata(auxdev, priv);
0553 
0554     /* Get the SDSi discovery table */
0555     disc_res = &intel_cap_dev->resource[0];
0556     disc_addr = devm_ioremap_resource(&auxdev->dev, disc_res);
0557     if (IS_ERR(disc_addr))
0558         return PTR_ERR(disc_addr);
0559 
0560     memcpy_fromio(&disc_table, disc_addr, DISC_TABLE_SIZE);
0561 
0562     priv->guid = disc_table.guid;
0563 
0564     /* Map the SDSi mailbox registers */
0565     ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res);
0566     if (ret)
0567         return ret;
0568 
0569     return 0;
0570 }
0571 
0572 static const struct auxiliary_device_id sdsi_aux_id_table[] = {
0573     { .name = "intel_vsec.sdsi" },
0574     {}
0575 };
0576 MODULE_DEVICE_TABLE(auxiliary, sdsi_aux_id_table);
0577 
0578 static struct auxiliary_driver sdsi_aux_driver = {
0579     .driver = {
0580         .dev_groups = sdsi_groups,
0581     },
0582     .id_table   = sdsi_aux_id_table,
0583     .probe      = sdsi_probe,
0584     /* No remove. All resources are handled under devm */
0585 };
0586 module_auxiliary_driver(sdsi_aux_driver);
0587 
0588 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
0589 MODULE_DESCRIPTION("Intel Software Defined Silicon driver");
0590 MODULE_LICENSE("GPL");