xref: /openbmc/linux/drivers/platform/x86/intel/sdsi.c (revision 980c3799)
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_MAX_PACKETS		4
55 
56 #define MBOX_OWNER_NONE			0x00
57 #define MBOX_OWNER_INBAND		0x01
58 
59 #define CTRL_RUN_BUSY			BIT(0)
60 #define CTRL_READ_WRITE			BIT(1)
61 #define CTRL_SOM			BIT(2)
62 #define CTRL_EOM			BIT(3)
63 #define CTRL_OWNER			GENMASK(5, 4)
64 #define CTRL_COMPLETE			BIT(6)
65 #define CTRL_READY			BIT(7)
66 #define CTRL_STATUS			GENMASK(15, 8)
67 #define CTRL_PACKET_SIZE		GENMASK(31, 16)
68 #define CTRL_MSG_SIZE			GENMASK(63, 48)
69 
70 #define DISC_TABLE_SIZE			12
71 #define DT_ACCESS_TYPE			GENMASK(3, 0)
72 #define DT_SIZE				GENMASK(27, 12)
73 #define DT_TBIR				GENMASK(2, 0)
74 #define DT_OFFSET(v)			((v) & GENMASK(31, 3))
75 
76 enum sdsi_command {
77 	SDSI_CMD_PROVISION_AKC		= 0x04,
78 	SDSI_CMD_PROVISION_CAP		= 0x08,
79 	SDSI_CMD_READ_STATE		= 0x10,
80 };
81 
82 struct sdsi_mbox_info {
83 	u64	*payload;
84 	u64	*buffer;
85 	int	size;
86 };
87 
88 struct disc_table {
89 	u32	access_info;
90 	u32	guid;
91 	u32	offset;
92 };
93 
94 struct sdsi_priv {
95 	struct mutex		mb_lock;	/* Mailbox access lock */
96 	struct device		*dev;
97 	void __iomem		*control_addr;
98 	void __iomem		*mbox_addr;
99 	void __iomem		*regs_addr;
100 	u32			guid;
101 	bool			sdsi_enabled;
102 };
103 
104 /* SDSi mailbox operations must be performed using 64bit mov instructions */
105 static __always_inline void
106 sdsi_memcpy64_toio(u64 __iomem *to, const u64 *from, size_t count_bytes)
107 {
108 	size_t count = count_bytes / sizeof(*to);
109 	int i;
110 
111 	for (i = 0; i < count; i++)
112 		writeq(from[i], &to[i]);
113 }
114 
115 static __always_inline void
116 sdsi_memcpy64_fromio(u64 *to, const u64 __iomem *from, size_t count_bytes)
117 {
118 	size_t count = count_bytes / sizeof(*to);
119 	int i;
120 
121 	for (i = 0; i < count; i++)
122 		to[i] = readq(&from[i]);
123 }
124 
125 static inline void sdsi_complete_transaction(struct sdsi_priv *priv)
126 {
127 	u64 control = FIELD_PREP(CTRL_COMPLETE, 1);
128 
129 	lockdep_assert_held(&priv->mb_lock);
130 	writeq(control, priv->control_addr);
131 }
132 
133 static int sdsi_status_to_errno(u32 status)
134 {
135 	switch (status) {
136 	case SDSI_MBOX_CMD_SUCCESS:
137 		return 0;
138 	case SDSI_MBOX_CMD_TIMEOUT:
139 		return -ETIMEDOUT;
140 	default:
141 		return -EIO;
142 	}
143 }
144 
145 static int sdsi_mbox_cmd_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info,
146 			      size_t *data_size)
147 {
148 	struct device *dev = priv->dev;
149 	u32 total, loop, eom, status, message_size;
150 	u64 control;
151 	int ret;
152 
153 	lockdep_assert_held(&priv->mb_lock);
154 
155 	/* Format and send the read command */
156 	control = FIELD_PREP(CTRL_EOM, 1) |
157 		  FIELD_PREP(CTRL_SOM, 1) |
158 		  FIELD_PREP(CTRL_RUN_BUSY, 1) |
159 		  FIELD_PREP(CTRL_PACKET_SIZE, info->size);
160 	writeq(control, priv->control_addr);
161 
162 	/* For reads, data sizes that are larger than the mailbox size are read in packets. */
163 	total = 0;
164 	loop = 0;
165 	do {
166 		int offset = SDSI_SIZE_MAILBOX * loop;
167 		void __iomem *addr = priv->mbox_addr + offset;
168 		u64 *buf = info->buffer + offset / SDSI_SIZE_CMD;
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, 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 run_busy bit */
247 	ret = readq_poll_timeout(priv->control_addr, control, !(control & CTRL_RUN_BUSY),
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;
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 	/* Write first qword of payload */
277 	writeq(info->payload[0], priv->mbox_addr);
278 
279 	/* Check for ownership */
280 	ret = readq_poll_timeout(priv->control_addr, control,
281 				 FIELD_GET(CTRL_OWNER, control) & MBOX_OWNER_INBAND,
282 				 MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
283 
284 	return ret;
285 }
286 
287 static int sdsi_mbox_write(struct sdsi_priv *priv, struct sdsi_mbox_info *info)
288 {
289 	int ret;
290 
291 	lockdep_assert_held(&priv->mb_lock);
292 
293 	ret = sdsi_mbox_acquire(priv, info);
294 	if (ret)
295 		return ret;
296 
297 	return sdsi_mbox_cmd_write(priv, info);
298 }
299 
300 static int sdsi_mbox_read(struct sdsi_priv *priv, struct sdsi_mbox_info *info, size_t *data_size)
301 {
302 	int ret;
303 
304 	lockdep_assert_held(&priv->mb_lock);
305 
306 	ret = sdsi_mbox_acquire(priv, info);
307 	if (ret)
308 		return ret;
309 
310 	return sdsi_mbox_cmd_read(priv, info, data_size);
311 }
312 
313 static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count,
314 			      enum sdsi_command command)
315 {
316 	struct sdsi_mbox_info info;
317 	int ret;
318 
319 	if (!priv->sdsi_enabled)
320 		return -EPERM;
321 
322 	if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD))
323 		return -EOVERFLOW;
324 
325 	/* Qword aligned message + command qword */
326 	info.size = round_up(count, SDSI_SIZE_CMD) + SDSI_SIZE_CMD;
327 
328 	info.payload = kzalloc(info.size, GFP_KERNEL);
329 	if (!info.payload)
330 		return -ENOMEM;
331 
332 	/* Copy message to payload buffer */
333 	memcpy(info.payload, buf, count);
334 
335 	/* Command is last qword of payload buffer */
336 	info.payload[(info.size - SDSI_SIZE_CMD) / SDSI_SIZE_CMD] = command;
337 
338 	ret = mutex_lock_interruptible(&priv->mb_lock);
339 	if (ret)
340 		goto free_payload;
341 	ret = sdsi_mbox_write(priv, &info);
342 	mutex_unlock(&priv->mb_lock);
343 
344 free_payload:
345 	kfree(info.payload);
346 
347 	if (ret)
348 		return ret;
349 
350 	return count;
351 }
352 
353 static ssize_t provision_akc_write(struct file *filp, struct kobject *kobj,
354 				   struct bin_attribute *attr, char *buf, loff_t off,
355 				   size_t count)
356 {
357 	struct device *dev = kobj_to_dev(kobj);
358 	struct sdsi_priv *priv = dev_get_drvdata(dev);
359 
360 	if (off)
361 		return -ESPIPE;
362 
363 	return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_AKC);
364 }
365 static BIN_ATTR_WO(provision_akc, SDSI_SIZE_WRITE_MSG);
366 
367 static ssize_t provision_cap_write(struct file *filp, struct kobject *kobj,
368 				   struct bin_attribute *attr, char *buf, loff_t off,
369 				   size_t count)
370 {
371 	struct device *dev = kobj_to_dev(kobj);
372 	struct sdsi_priv *priv = dev_get_drvdata(dev);
373 
374 	if (off)
375 		return -ESPIPE;
376 
377 	return sdsi_provision(priv, buf, count, SDSI_CMD_PROVISION_CAP);
378 }
379 static BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG);
380 
381 static long state_certificate_read(struct file *filp, struct kobject *kobj,
382 				   struct bin_attribute *attr, char *buf, loff_t off,
383 				   size_t count)
384 {
385 	struct device *dev = kobj_to_dev(kobj);
386 	struct sdsi_priv *priv = dev_get_drvdata(dev);
387 	u64 command = SDSI_CMD_READ_STATE;
388 	struct sdsi_mbox_info info;
389 	size_t size;
390 	int ret;
391 
392 	if (!priv->sdsi_enabled)
393 		return -EPERM;
394 
395 	if (off)
396 		return 0;
397 
398 	/* Buffer for return data */
399 	info.buffer = kmalloc(SDSI_SIZE_READ_MSG, GFP_KERNEL);
400 	if (!info.buffer)
401 		return -ENOMEM;
402 
403 	info.payload = &command;
404 	info.size = sizeof(command);
405 
406 	ret = mutex_lock_interruptible(&priv->mb_lock);
407 	if (ret)
408 		goto free_buffer;
409 	ret = sdsi_mbox_read(priv, &info, &size);
410 	mutex_unlock(&priv->mb_lock);
411 	if (ret < 0)
412 		goto free_buffer;
413 
414 	if (size > count)
415 		size = count;
416 
417 	memcpy(buf, info.buffer, size);
418 
419 free_buffer:
420 	kfree(info.buffer);
421 
422 	if (ret)
423 		return ret;
424 
425 	return size;
426 }
427 static BIN_ATTR(state_certificate, 0400, state_certificate_read, NULL, SDSI_SIZE_READ_MSG);
428 
429 static ssize_t registers_read(struct file *filp, struct kobject *kobj,
430 			      struct bin_attribute *attr, char *buf, loff_t off,
431 			      size_t count)
432 {
433 	struct device *dev = kobj_to_dev(kobj);
434 	struct sdsi_priv *priv = dev_get_drvdata(dev);
435 	void __iomem *addr = priv->regs_addr;
436 
437 	memcpy_fromio(buf, addr + off, count);
438 
439 	return count;
440 }
441 static BIN_ATTR(registers, 0400, registers_read, NULL, SDSI_SIZE_REGS);
442 
443 static struct bin_attribute *sdsi_bin_attrs[] = {
444 	&bin_attr_registers,
445 	&bin_attr_state_certificate,
446 	&bin_attr_provision_akc,
447 	&bin_attr_provision_cap,
448 	NULL
449 };
450 
451 static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf)
452 {
453 	struct sdsi_priv *priv = dev_get_drvdata(dev);
454 
455 	return sysfs_emit(buf, "0x%x\n", priv->guid);
456 }
457 static DEVICE_ATTR_RO(guid);
458 
459 static struct attribute *sdsi_attrs[] = {
460 	&dev_attr_guid.attr,
461 	NULL
462 };
463 
464 static const struct attribute_group sdsi_group = {
465 	.attrs = sdsi_attrs,
466 	.bin_attrs = sdsi_bin_attrs,
467 };
468 __ATTRIBUTE_GROUPS(sdsi);
469 
470 static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent,
471 				   struct disc_table *disc_table, struct resource *disc_res)
472 {
473 	u32 access_type = FIELD_GET(DT_ACCESS_TYPE, disc_table->access_info);
474 	u32 size = FIELD_GET(DT_SIZE, disc_table->access_info);
475 	u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset);
476 	u32 offset = DT_OFFSET(disc_table->offset);
477 	u32 features_offset;
478 	struct resource res = {};
479 
480 	/* Starting location of SDSi MMIO region based on access type */
481 	switch (access_type) {
482 	case ACCESS_TYPE_LOCAL:
483 		if (tbir) {
484 			dev_err(priv->dev, "Unsupported BAR index %u for access type %u\n",
485 				tbir, access_type);
486 			return -EINVAL;
487 		}
488 
489 		/*
490 		 * For access_type LOCAL, the base address is as follows:
491 		 * base address = end of discovery region + base offset + 1
492 		 */
493 		res.start = disc_res->end + offset + 1;
494 		break;
495 
496 	case ACCESS_TYPE_BARID:
497 		res.start = pci_resource_start(parent, tbir) + offset;
498 		break;
499 
500 	default:
501 		dev_err(priv->dev, "Unrecognized access_type %u\n", access_type);
502 		return -EINVAL;
503 	}
504 
505 	res.end = res.start + size * sizeof(u32) - 1;
506 	res.flags = IORESOURCE_MEM;
507 
508 	priv->control_addr = devm_ioremap_resource(priv->dev, &res);
509 	if (IS_ERR(priv->control_addr))
510 		return PTR_ERR(priv->control_addr);
511 
512 	priv->mbox_addr = priv->control_addr + SDSI_SIZE_CONTROL;
513 	priv->regs_addr = priv->mbox_addr + SDSI_SIZE_MAILBOX;
514 
515 	features_offset = readq(priv->regs_addr + SDSI_ENABLED_FEATURES_OFFSET);
516 	priv->sdsi_enabled = !!(features_offset & SDSI_ENABLED);
517 
518 	return 0;
519 }
520 
521 static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
522 {
523 	struct intel_vsec_device *intel_cap_dev = auxdev_to_ivdev(auxdev);
524 	struct disc_table disc_table;
525 	struct resource *disc_res;
526 	void __iomem *disc_addr;
527 	struct sdsi_priv *priv;
528 	int ret;
529 
530 	priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
531 	if (!priv)
532 		return -ENOMEM;
533 
534 	priv->dev = &auxdev->dev;
535 	mutex_init(&priv->mb_lock);
536 	auxiliary_set_drvdata(auxdev, priv);
537 
538 	/* Get the SDSi discovery table */
539 	disc_res = &intel_cap_dev->resource[0];
540 	disc_addr = devm_ioremap_resource(&auxdev->dev, disc_res);
541 	if (IS_ERR(disc_addr))
542 		return PTR_ERR(disc_addr);
543 
544 	memcpy_fromio(&disc_table, disc_addr, DISC_TABLE_SIZE);
545 
546 	priv->guid = disc_table.guid;
547 
548 	/* Map the SDSi mailbox registers */
549 	ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res);
550 	if (ret)
551 		return ret;
552 
553 	return 0;
554 }
555 
556 static const struct auxiliary_device_id sdsi_aux_id_table[] = {
557 	{ .name = "intel_vsec.sdsi" },
558 	{}
559 };
560 MODULE_DEVICE_TABLE(auxiliary, sdsi_aux_id_table);
561 
562 static struct auxiliary_driver sdsi_aux_driver = {
563 	.driver = {
564 		.dev_groups = sdsi_groups,
565 	},
566 	.id_table	= sdsi_aux_id_table,
567 	.probe		= sdsi_probe,
568 	/* No remove. All resources are handled under devm */
569 };
570 module_auxiliary_driver(sdsi_aux_driver);
571 
572 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
573 MODULE_DESCRIPTION("Intel Software Defined Silicon driver");
574 MODULE_LICENSE("GPL");
575