0001
0002
0003
0004
0005
0006
0007
0008
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
0037
0038
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;
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
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
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
0165 total = 0;
0166 loop = 0;
0167 do {
0168 void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop);
0169 u32 packet_size;
0170
0171
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
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
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
0235 sdsi_memcpy64_toio(priv->mbox_addr + SDSI_SIZE_CMD, info->payload + 1,
0236 info->size - SDSI_SIZE_CMD);
0237
0238
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
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
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
0278
0279
0280
0281 do {
0282
0283 writeq(info->payload[0], priv->mbox_addr);
0284
0285
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
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
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
0349 memcpy(info.payload, buf, count);
0350
0351
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
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
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
0507
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
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
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
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");