xref: /openbmc/linux/drivers/platform/x86/intel/sdsi.c (revision b92dd117)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Software Defined Silicon driver
4  *
5  * Copyright (c) 2022, Intel Corporation.
6  * All Rights Reserved.
7  *
8  * Author: "David E. Box" <david.e.box@linux.intel.com>
9  */
10 
11 #include <linux/auxiliary_bus.h>
12 #include <linux/bits.h>
13 #include <linux/bitfield.h>
14 #include <linux/device.h>
15 #include <linux/iopoll.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/pci.h>
19 #include <linux/slab.h>
20 #include <linux/sysfs.h>
21 #include <linux/types.h>
22 #include <linux/uaccess.h>
23 
24 #include "vsec.h"
25 
26 #define ACCESS_TYPE_BARID		2
27 #define ACCESS_TYPE_LOCAL		3
28 
29 #define SDSI_MIN_SIZE_DWORDS		276
30 #define SDSI_SIZE_CONTROL		8
31 #define SDSI_SIZE_MAILBOX		1024
32 #define SDSI_SIZE_REGS			72
33 #define SDSI_SIZE_CMD			sizeof(u64)
34 
35 /*
36  * Write messages are currently up to the size of the mailbox
37  * while read messages are up to 4 times the size of the
38  * mailbox, sent in packets
39  */
40 #define SDSI_SIZE_WRITE_MSG		SDSI_SIZE_MAILBOX
41 #define SDSI_SIZE_READ_MSG		(SDSI_SIZE_MAILBOX * 4)
42 
43 #define SDSI_ENABLED_FEATURES_OFFSET	16
44 #define SDSI_ENABLED			BIT(3)
45 #define SDSI_SOCKET_ID_OFFSET		64
46 #define SDSI_SOCKET_ID			GENMASK(3, 0)
47 
48 #define SDSI_MBOX_CMD_SUCCESS		0x40
49 #define SDSI_MBOX_CMD_TIMEOUT		0x80
50 
51 #define MBOX_TIMEOUT_US			2000
52 #define MBOX_TIMEOUT_ACQUIRE_US		1000
53 #define MBOX_POLLING_PERIOD_US		100
54 #define MBOX_ACQUIRE_NUM_RETRIES	5
55 #define MBOX_ACQUIRE_RETRY_DELAY_MS	500
56 #define MBOX_MAX_PACKETS		4
57 
58 #define MBOX_OWNER_NONE			0x00
59 #define MBOX_OWNER_INBAND		0x01
60 
61 #define CTRL_RUN_BUSY			BIT(0)
62 #define CTRL_READ_WRITE			BIT(1)
63 #define CTRL_SOM			BIT(2)
64 #define CTRL_EOM			BIT(3)
65 #define CTRL_OWNER			GENMASK(5, 4)
66 #define CTRL_COMPLETE			BIT(6)
67 #define CTRL_READY			BIT(7)
68 #define CTRL_STATUS			GENMASK(15, 8)
69 #define CTRL_PACKET_SIZE		GENMASK(31, 16)
70 #define CTRL_MSG_SIZE			GENMASK(63, 48)
71 
72 #define DISC_TABLE_SIZE			12
73 #define DT_ACCESS_TYPE			GENMASK(3, 0)
74 #define DT_SIZE				GENMASK(27, 12)
75 #define DT_TBIR				GENMASK(2, 0)
76 #define DT_OFFSET(v)			((v) & GENMASK(31, 3))
77 
78 enum sdsi_command {
79 	SDSI_CMD_PROVISION_AKC		= 0x04,
80 	SDSI_CMD_PROVISION_CAP		= 0x08,
81 	SDSI_CMD_READ_STATE		= 0x10,
82 };
83 
84 struct sdsi_mbox_info {
85 	u64	*payload;
86 	void	*buffer;
87 	int	size;
88 };
89 
90 struct disc_table {
91 	u32	access_info;
92 	u32	guid;
93 	u32	offset;
94 };
95 
96 struct sdsi_priv {
97 	struct mutex		mb_lock;	/* Mailbox access lock */
98 	struct device		*dev;
99 	void __iomem		*control_addr;
100 	void __iomem		*mbox_addr;
101 	void __iomem		*regs_addr;
102 	u32			guid;
103 	bool			sdsi_enabled;
104 };
105 
106 /* SDSi mailbox operations must be performed using 64bit mov instructions */
107 static __always_inline void
108 sdsi_memcpy64_toio(u64 __iomem *to, const u64 *from, size_t count_bytes)
109 {
110 	size_t count = count_bytes / sizeof(*to);
111 	int i;
112 
113 	for (i = 0; i < count; i++)
114 		writeq(from[i], &to[i]);
115 }
116 
117 static __always_inline void
118 sdsi_memcpy64_fromio(u64 *to, const u64 __iomem *from, size_t count_bytes)
119 {
120 	size_t count = count_bytes / sizeof(*to);
121 	int i;
122 
123 	for (i = 0; i < count; i++)
124 		to[i] = readq(&from[i]);
125 }
126 
127 static inline void sdsi_complete_transaction(struct sdsi_priv *priv)
128 {
129 	u64 control = FIELD_PREP(CTRL_COMPLETE, 1);
130 
131 	lockdep_assert_held(&priv->mb_lock);
132 	writeq(control, priv->control_addr);
133 }
134 
135 static int sdsi_status_to_errno(u32 status)
136 {
137 	switch (status) {
138 	case SDSI_MBOX_CMD_SUCCESS:
139 		return 0;
140 	case SDSI_MBOX_CMD_TIMEOUT:
141 		return -ETIMEDOUT;
142 	default:
143 		return -EIO;
144 	}
145 }
146 
147 static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
148 			      size_t *data_size)
149 {
150 	struct device *dev = priv->dev;
151 	u32 total, loop, eom, status, message_size;
152 	u64 control;
153 	int ret;
154 
155 	lockdep_assert_held(&priv->mb_lock);
156 
157 	/* Format and send the read command */
158 	control = FIELD_PREP(CTRL_EOM, 1) |
159 		  FIELD_PREP(CTRL_SOM, 1) |
160 		  FIELD_PREP(CTRL_RUN_BUSY, 1) |
161 		  FIELD_PREP(CTRL_PACKET_SIZE, info->size);
162 	writeq(control, priv->control_addr);
163 
164 	/* For reads, data sizes that are larger than the mailbox size are read in packets. */
165 	total = 0;
166 	loop = 0;
167 	do {
168 		void *buf = info->buffer + (SDSI_SIZE_MAILBOX * loop);
169 		u32 packet_size;
170 
171 		/* Poll on ready bit */
172 		ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
173 					 MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
174 		if (ret)
175 			break;
176 
177 		eom = FIELD_GET(CTRL_EOM, control);
178 		status = FIELD_GET(CTRL_STATUS, control);
179 		packet_size = FIELD_GET(CTRL_PACKET_SIZE, control);
180 		message_size = FIELD_GET(CTRL_MSG_SIZE, control);
181 
182 		ret = sdsi_status_to_errno(status);
183 		if (ret)
184 			break;
185 
186 		/* Only the last packet can be less than the mailbox size. */
187 		if (!eom && packet_size != SDSI_SIZE_MAILBOX) {
188 			dev_err(dev, "Invalid packet size\n");
189 			ret = -EPROTO;
190 			break;
191 		}
192 
193 		if (packet_size > SDSI_SIZE_MAILBOX) {
194 			dev_err(dev, "Packet size too large\n");
195 			ret = -EPROTO;
196 			break;
197 		}
198 
199 		sdsi_memcpy64_fromio(buf, priv->mbox_addr, round_up(packet_size, SDSI_SIZE_CMD));
200 
201 		total += packet_size;
202 
203 		sdsi_complete_transaction(priv);
204 	} while (!eom && ++loop < MBOX_MAX_PACKETS);
205 
206 	if (ret) {
207 		sdsi_complete_transaction(priv);
208 		return ret;
209 	}
210 
211 	if (!eom) {
212 		dev_err(dev, "Exceeded read attempts\n");
213 		return -EPROTO;
214 	}
215 
216 	/* Message size check is only valid for multi-packet transfers */
217 	if (loop && total != message_size)
218 		dev_warn(dev, "Read count %u differs from expected count %u\n",
219 			 total, message_size);
220 
221 	*data_size = total;
222 
223 	return 0;
224 }
225 
226 static int sdsi_mbox_cmd_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
227 {
228 	u64 control;
229 	u32 status;
230 	int ret;
231 
232 	lockdep_assert_held(&priv->mb_lock);
233 
234 	/* Write rest of the payload */
235 	sdsi_memcpy64_toio(priv->mbox_addr + SDSI_SIZE_CMD, info->payload + 1,
236 			   info->size - SDSI_SIZE_CMD);
237 
238 	/* Format and send the write command */
239 	control = FIELD_PREP(CTRL_EOM, 1) |
240 		  FIELD_PREP(CTRL_SOM, 1) |
241 		  FIELD_PREP(CTRL_RUN_BUSY, 1) |
242 		  FIELD_PREP(CTRL_READ_WRITE, 1) |
243 		  FIELD_PREP(CTRL_PACKET_SIZE, info->size);
244 	writeq(control, priv->control_addr);
245 
246 	/* Poll on ready bit */
247 	ret = readq_poll_timeout(priv->control_addr, control, control & CTRL_READY,
248 				 MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_US);
249 
250 	if (ret)
251 		goto release_mbox;
252 
253 	status = FIELD_GET(CTRL_STATUS, control);
254 	ret = sdsi_status_to_errno(status);
255 
256 release_mbox:
257 	sdsi_complete_transaction(priv);
258 
259 	return ret;
260 }
261 
262 static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
263 {
264 	u64 control;
265 	u32 owner;
266 	int ret, retries = 0;
267 
268 	lockdep_assert_held(&priv->mb_lock);
269 
270 	/* Check mailbox is available */
271 	control = readq(priv->control_addr);
272 	owner = FIELD_GET(CTRL_OWNER, control);
273 	if (owner != MBOX_OWNER_NONE)
274 		return -EBUSY;
275 
276 	/*
277 	 * If there has been no recent transaction and no one owns the mailbox,
278 	 * we should acquire it in under 1ms. However, if we've accessed it
279 	 * recently it may take up to 2.1 seconds to acquire it again.
280 	 */
281 	do {
282 		/* Write first qword of payload */
283 		writeq(info->payload[0], priv->mbox_addr);
284 
285 		/* Check for ownership */
286 		ret = readq_poll_timeout(priv->control_addr, control,
287 			FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_INBAND,
288 			MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
289 
290 		if (FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_NONE &&
291 		    retries++ < MBOX_ACQUIRE_NUM_RETRIES) {
292 			msleep(MBOX_ACQUIRE_RETRY_DELAY_MS);
293 			continue;
294 		}
295 
296 		/* Either we got it or someone else did. */
297 		break;
298 	} while (true);
299 
300 	return ret;
301 }
302 
303 static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
304 {
305 	int ret;
306 
307 	lockdep_assert_held(&priv->mb_lock);
308 
309 	ret = sdsi_mbox_acquire(priv, info);
310 	if (ret)
311 		return ret;
312 
313 	return sdsi_mbox_cmd_write(priv, info);
314 }
315 
316 static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, size_t *data_size)
317 {
318 	int ret;
319 
320 	lockdep_assert_held(&priv->mb_lock);
321 
322 	ret = sdsi_mbox_acquire(priv, info);
323 	if (ret)
324 		return ret;
325 
326 	return sdsi_mbox_cmd_read(priv, info, data_size);
327 }
328 
329 static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
330 			      enum sdsi_command command)
331 {
332 	struct sdsi_mbox_info info;
333 	int ret;
334 
335 	if (!priv->sdsi_enabled)
336 		return -EPERM;
337 
338 	if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
339 		return -EOVERFLOW;
340 
341 	/* Qword aligned message + command qword */
342 	info.size = round_up(count, SDSI_SIZE_CMD) + SDSI_SIZE_CMD;
343 
344 	info.payload = kzalloc(info.size, GFP_KERNEL);
345 	if (!info.payload)
346 		return -ENOMEM;
347 
348 	/* Copy message to payload buffer */
349 	memcpy(info.payload, buf, count);
350 
351 	/* Command is last qword of payload buffer */
352 	info.payload[(info.size - SDSI_SIZE_CMD) / SDSI_SIZE_CMD] = command;
353 
354 	ret = mutex_lock_interruptible(&priv->mb_lock);
355 	if (ret)
356 		goto free_payload;
357 	ret = sdsi_mbox_write(priv, &info);
358 	mutex_unlock(&priv->mb_lock);
359 
360 free_payload:
361 	kfree(info.payload);
362 
363 	if (ret)
364 		return ret;
365 
366 	return count;
367 }
368 
369 static ssize_t provision_akc_write(struct file *filp, struct kobject *kobj,
370 				   struct bin_attribute *attr, char *buf, loff_t off,
371 				   size_t count)
372 {
373 	struct device *dev = kobj_to_dev(kobj);
374 	struct sdsi_priv *priv = dev_get_drvdata(dev);
375 
376 	if (off)
377 		return -ESPIPE;
378 
379 	return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_AKC);
380 }
381 static BIN_ATTR_WO(provision_akc, SDSI_SIZE_WRITE_MSG);
382 
383 static ssize_t provision_cap_write(struct file *filp, struct kobject *kobj,
384 				   struct bin_attribute *attr, char *buf, loff_t off,
385 				   size_t count)
386 {
387 	struct device *dev = kobj_to_dev(kobj);
388 	struct sdsi_priv *priv = dev_get_drvdata(dev);
389 
390 	if (off)
391 		return -ESPIPE;
392 
393 	return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_CAP);
394 }
395 static BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG);
396 
397 static long state_certificate_read(struct file *filp, struct kobject *kobj,
398 				   struct bin_attribute *attr, char *buf, loff_t off,
399 				   size_t count)
400 {
401 	struct device *dev = kobj_to_dev(kobj);
402 	struct sdsi_priv *priv = dev_get_drvdata(dev);
403 	u64 command = SDSI_CMD_READ_STATE;
404 	struct sdsi_mbox_info info;
405 	size_t size;
406 	int ret;
407 
408 	if (!priv->sdsi_enabled)
409 		return -EPERM;
410 
411 	if (off)
412 		return 0;
413 
414 	/* Buffer for return data */
415 	info.buffer = kmalloc(SDSI_SIZE_READ_MSG, GFP_KERNEL);
416 	if (!info.buffer)
417 		return -ENOMEM;
418 
419 	info.payload = &command;
420 	info.size = sizeof(command);
421 
422 	ret = mutex_lock_interruptible(&priv->mb_lock);
423 	if (ret)
424 		goto free_buffer;
425 	ret = sdsi_mbox_read(priv, &info, &size);
426 	mutex_unlock(&priv->mb_lock);
427 	if (ret < 0)
428 		goto free_buffer;
429 
430 	if (size > count)
431 		size = count;
432 
433 	memcpy(buf, info.buffer, size);
434 
435 free_buffer:
436 	kfree(info.buffer);
437 
438 	if (ret)
439 		return ret;
440 
441 	return size;
442 }
443 static BIN_ATTR(state_certificate, 0400, state_certificate_read, NULL, SDSI_SIZE_READ_MSG);
444 
445 static ssize_t registers_read(struct file *filp, struct kobject *kobj,
446 			      struct bin_attribute *attr, char *buf, loff_t off,
447 			      size_t count)
448 {
449 	struct device *dev = kobj_to_dev(kobj);
450 	struct sdsi_priv *priv = dev_get_drvdata(dev);
451 	void __iomem *addr = priv->regs_addr;
452 
453 	memcpy_fromio(buf, addr + off, count);
454 
455 	return count;
456 }
457 static BIN_ATTR(registers, 0400, registers_read, NULL, SDSI_SIZE_REGS);
458 
459 static struct bin_attribute *sdsi_bin_attrs[] = {
460 	&bin_attr_registers,
461 	&bin_attr_state_certificate,
462 	&bin_attr_provision_akc,
463 	&bin_attr_provision_cap,
464 	NULL
465 };
466 
467 static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf)
468 {
469 	struct sdsi_priv *priv = dev_get_drvdata(dev);
470 
471 	return sysfs_emit(buf, "0x%x\n", priv->guid);
472 }
473 static DEVICE_ATTR_RO(guid);
474 
475 static struct attribute *sdsi_attrs[] = {
476 	&dev_attr_guid.attr,
477 	NULL
478 };
479 
480 static const struct attribute_group sdsi_group = {
481 	.attrs = sdsi_attrs,
482 	.bin_attrs = sdsi_bin_attrs,
483 };
484 __ATTRIBUTE_GROUPS(sdsi);
485 
486 static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent,
487 				   struct disc_table *disc_table, struct resource *disc_res)
488 {
489 	u32 access_type = FIELD_GET(DT_ACCESS_TYPE, disc_table->access_info);
490 	u32 size = FIELD_GET(DT_SIZE, disc_table->access_info);
491 	u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset);
492 	u32 offset = DT_OFFSET(disc_table->offset);
493 	u32 features_offset;
494 	struct resource res = {};
495 
496 	/* Starting location of SDSi MMIO region based on access type */
497 	switch (access_type) {
498 	case ACCESS_TYPE_LOCAL:
499 		if (tbir) {
500 			dev_err(priv->dev, "Unsupported BAR index %u for access type %u\n",
501 				tbir, access_type);
502 			return -EINVAL;
503 		}
504 
505 		/*
506 		 * For access_type LOCAL, the base address is as follows:
507 		 * base address = end of discovery region + base offset + 1
508 		 */
509 		res.start = disc_res->end + offset + 1;
510 		break;
511 
512 	case ACCESS_TYPE_BARID:
513 		res.start = pci_resource_start(parent, tbir) + offset;
514 		break;
515 
516 	default:
517 		dev_err(priv->dev, "Unrecognized access_type %u\n", access_type);
518 		return -EINVAL;
519 	}
520 
521 	res.end = res.start + size * sizeof(u32) - 1;
522 	res.flags = IORESOURCE_MEM;
523 
524 	priv->control_addr = devm_ioremap_resource(priv->dev, &res);
525 	if (IS_ERR(priv->control_addr))
526 		return PTR_ERR(priv->control_addr);
527 
528 	priv->mbox_addr = priv->control_addr + SDSI_SIZE_CONTROL;
529 	priv->regs_addr = priv->mbox_addr + SDSI_SIZE_MAILBOX;
530 
531 	features_offset = readq(priv->regs_addr + SDSI_ENABLED_FEATURES_OFFSET);
532 	priv->sdsi_enabled = !!(features_offset & SDSI_ENABLED);
533 
534 	return 0;
535 }
536 
537 static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
538 {
539 	struct intel_vsec_device *intel_cap_dev = auxdev_to_ivdev(auxdev);
540 	struct disc_table disc_table;
541 	struct resource *disc_res;
542 	void __iomem *disc_addr;
543 	struct sdsi_priv *priv;
544 	int ret;
545 
546 	priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
547 	if (!priv)
548 		return -ENOMEM;
549 
550 	priv->dev = &auxdev->dev;
551 	mutex_init(&priv->mb_lock);
552 	auxiliary_set_drvdata(auxdev, priv);
553 
554 	/* Get the SDSi discovery table */
555 	disc_res = &intel_cap_dev->resource[0];
556 	disc_addr = devm_ioremap_resource(&auxdev->dev, disc_res);
557 	if (IS_ERR(disc_addr))
558 		return PTR_ERR(disc_addr);
559 
560 	memcpy_fromio(&disc_table, disc_addr, DISC_TABLE_SIZE);
561 
562 	priv->guid = disc_table.guid;
563 
564 	/* Map the SDSi mailbox registers */
565 	ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res);
566 	if (ret)
567 		return ret;
568 
569 	return 0;
570 }
571 
572 static const struct auxiliary_device_id sdsi_aux_id_table[] = {
573 	{ .name = "intel_vsec.sdsi" },
574 	{}
575 };
576 MODULE_DEVICE_TABLE(auxiliary, sdsi_aux_id_table);
577 
578 static struct auxiliary_driver sdsi_aux_driver = {
579 	.driver = {
580 		.dev_groups = sdsi_groups,
581 	},
582 	.id_table	= sdsi_aux_id_table,
583 	.probe		= sdsi_probe,
584 	/* No remove. All resources are handled under devm */
585 };
586 module_auxiliary_driver(sdsi_aux_driver);
587 
588 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
589 MODULE_DESCRIPTION("Intel Software Defined Silicon driver");
590 MODULE_LICENSE("GPL");
591