brintos

brintos / linux-shallow public Read only

0
0
Text · 7.9 KiB · 5e1d807 Raw
368 lines · c
1// SPDX-License-Identifier: MIT2/*3 * AMD Trusted Execution Environment (TEE) interface4 *5 * Author: Rijo Thomas <Rijo-john.Thomas@amd.com>6 * Author: Devaraj Rangasamy <Devaraj.Rangasamy@amd.com>7 *8 * Copyright (C) 2019,2021 Advanced Micro Devices, Inc.9 */10 11#include <linux/bitfield.h>12#include <linux/types.h>13#include <linux/mutex.h>14#include <linux/delay.h>15#include <linux/slab.h>16#include <linux/gfp.h>17#include <linux/psp.h>18#include <linux/psp-tee.h>19 20#include "psp-dev.h"21#include "tee-dev.h"22 23static bool psp_dead;24 25static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size)26{27	struct ring_buf_manager *rb_mgr = &tee->rb_mgr;28	void *start_addr;29 30	if (!ring_size)31		return -EINVAL;32 33	/* We need actual physical address instead of DMA address, since34	 * Trusted OS running on AMD Secure Processor will map this region35	 */36	start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size));37	if (!start_addr)38		return -ENOMEM;39 40	memset(start_addr, 0x0, ring_size);41	rb_mgr->ring_start = start_addr;42	rb_mgr->ring_size = ring_size;43	rb_mgr->ring_pa = __psp_pa(start_addr);44	mutex_init(&rb_mgr->mutex);45 46	return 0;47}48 49static void tee_free_ring(struct psp_tee_device *tee)50{51	struct ring_buf_manager *rb_mgr = &tee->rb_mgr;52 53	if (!rb_mgr->ring_start)54		return;55 56	free_pages((unsigned long)rb_mgr->ring_start,57		   get_order(rb_mgr->ring_size));58 59	rb_mgr->ring_start = NULL;60	rb_mgr->ring_size = 0;61	rb_mgr->ring_pa = 0;62	mutex_destroy(&rb_mgr->mutex);63}64 65static66struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee)67{68	struct tee_init_ring_cmd *cmd;69 70	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);71	if (!cmd)72		return NULL;73 74	cmd->hi_addr = upper_32_bits(tee->rb_mgr.ring_pa);75	cmd->low_addr = lower_32_bits(tee->rb_mgr.ring_pa);76	cmd->size = tee->rb_mgr.ring_size;77 78	dev_dbg(tee->dev, "tee: ring address: high = 0x%x low = 0x%x size = %u\n",79		cmd->hi_addr, cmd->low_addr, cmd->size);80 81	return cmd;82}83 84static inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd)85{86	kfree(cmd);87}88 89static int tee_init_ring(struct psp_tee_device *tee)90{91	int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);92	struct tee_init_ring_cmd *cmd;93	unsigned int reg;94	int ret;95 96	BUILD_BUG_ON(sizeof(struct tee_ring_cmd) != 1024);97 98	ret = tee_alloc_ring(tee, ring_size);99	if (ret) {100		dev_err(tee->dev, "tee: ring allocation failed %d\n", ret);101		return ret;102	}103 104	tee->rb_mgr.wptr = 0;105 106	cmd = tee_alloc_cmd_buffer(tee);107	if (!cmd) {108		tee_free_ring(tee);109		return -ENOMEM;110	}111 112	/* Send command buffer details to Trusted OS by writing to113	 * CPU-PSP message registers114	 */115	ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,116				  TEE_DEFAULT_CMD_TIMEOUT, &reg);117	if (ret) {118		dev_err(tee->dev, "tee: ring init command timed out, disabling TEE support\n");119		tee_free_ring(tee);120		psp_dead = true;121		goto free_buf;122	}123 124	if (FIELD_GET(PSP_CMDRESP_STS, reg)) {125		dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",126			FIELD_GET(PSP_CMDRESP_STS, reg));127		tee_free_ring(tee);128		ret = -EIO;129	}130 131free_buf:132	tee_free_cmd_buffer(cmd);133 134	return ret;135}136 137static void tee_destroy_ring(struct psp_tee_device *tee)138{139	unsigned int reg;140	int ret;141 142	if (!tee->rb_mgr.ring_start)143		return;144 145	if (psp_dead)146		goto free_ring;147 148	ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL,149				  TEE_DEFAULT_CMD_TIMEOUT, &reg);150	if (ret) {151		dev_err(tee->dev, "tee: ring destroy command timed out, disabling TEE support\n");152		psp_dead = true;153	} else if (FIELD_GET(PSP_CMDRESP_STS, reg)) {154		dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n",155			FIELD_GET(PSP_CMDRESP_STS, reg));156	}157 158free_ring:159	tee_free_ring(tee);160}161 162int tee_dev_init(struct psp_device *psp)163{164	struct device *dev = psp->dev;165	struct psp_tee_device *tee;166	int ret;167 168	ret = -ENOMEM;169	tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL);170	if (!tee)171		goto e_err;172 173	psp->tee_data = tee;174 175	tee->dev = dev;176	tee->psp = psp;177 178	tee->io_regs = psp->io_regs;179 180	tee->vdata = (struct tee_vdata *)psp->vdata->tee;181	if (!tee->vdata) {182		ret = -ENODEV;183		dev_err(dev, "tee: missing driver data\n");184		goto e_err;185	}186 187	ret = tee_init_ring(tee);188	if (ret) {189		dev_err(dev, "tee: failed to init ring buffer\n");190		goto e_err;191	}192 193	dev_notice(dev, "tee enabled\n");194 195	return 0;196 197e_err:198	psp->tee_data = NULL;199 200	dev_notice(dev, "tee initialization failed\n");201 202	return ret;203}204 205void tee_dev_destroy(struct psp_device *psp)206{207	struct psp_tee_device *tee = psp->tee_data;208 209	if (!tee)210		return;211 212	tee_destroy_ring(tee);213}214 215static int tee_submit_cmd(struct psp_tee_device *tee, enum tee_cmd_id cmd_id,216			  void *buf, size_t len, struct tee_ring_cmd **resp)217{218	struct tee_ring_cmd *cmd;219	int nloop = 1000, ret = 0;220	u32 rptr;221 222	*resp = NULL;223 224	mutex_lock(&tee->rb_mgr.mutex);225 226	/* Loop until empty entry found in ring buffer */227	do {228		/* Get pointer to ring buffer command entry */229		cmd = (struct tee_ring_cmd *)230			(tee->rb_mgr.ring_start + tee->rb_mgr.wptr);231 232		rptr = ioread32(tee->io_regs + tee->vdata->ring_rptr_reg);233 234		/* Check if ring buffer is full or command entry is waiting235		 * for response from TEE236		 */237		if (!(tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||238		      cmd->flag == CMD_WAITING_FOR_RESPONSE))239			break;240 241		dev_dbg(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n",242			rptr, tee->rb_mgr.wptr);243 244		/* Wait if ring buffer is full or TEE is processing data */245		mutex_unlock(&tee->rb_mgr.mutex);246		schedule_timeout_interruptible(msecs_to_jiffies(10));247		mutex_lock(&tee->rb_mgr.mutex);248 249	} while (--nloop);250 251	if (!nloop &&252	    (tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||253	     cmd->flag == CMD_WAITING_FOR_RESPONSE)) {254		dev_err(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u response flag %u\n",255			rptr, tee->rb_mgr.wptr, cmd->flag);256		ret = -EBUSY;257		goto unlock;258	}259 260	/* Do not submit command if PSP got disabled while processing any261	 * command in another thread262	 */263	if (psp_dead) {264		ret = -EBUSY;265		goto unlock;266	}267 268	/* Write command data into ring buffer */269	cmd->cmd_id = cmd_id;270	cmd->cmd_state = TEE_CMD_STATE_INIT;271	memset(&cmd->buf[0], 0, sizeof(cmd->buf));272	memcpy(&cmd->buf[0], buf, len);273 274	/* Indicate driver is waiting for response */275	cmd->flag = CMD_WAITING_FOR_RESPONSE;276 277	/* Update local copy of write pointer */278	tee->rb_mgr.wptr += sizeof(struct tee_ring_cmd);279	if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size)280		tee->rb_mgr.wptr = 0;281 282	/* Trigger interrupt to Trusted OS */283	iowrite32(tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg);284 285	/* The response is provided by Trusted OS in same286	 * location as submitted data entry within ring buffer.287	 */288	*resp = cmd;289 290unlock:291	mutex_unlock(&tee->rb_mgr.mutex);292 293	return ret;294}295 296static int tee_wait_cmd_completion(struct psp_tee_device *tee,297				   struct tee_ring_cmd *resp,298				   unsigned int timeout)299{300	/* ~1ms sleep per loop => nloop = timeout * 1000 */301	int nloop = timeout * 1000;302 303	while (--nloop) {304		if (resp->cmd_state == TEE_CMD_STATE_COMPLETED)305			return 0;306 307		usleep_range(1000, 1100);308	}309 310	dev_err(tee->dev, "tee: command 0x%x timed out, disabling PSP\n",311		resp->cmd_id);312 313	psp_dead = true;314 315	return -ETIMEDOUT;316}317 318int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len,319			u32 *status)320{321	struct psp_device *psp = psp_get_master_device();322	struct psp_tee_device *tee;323	struct tee_ring_cmd *resp;324	int ret;325 326	if (!buf || !status || !len || len > sizeof(resp->buf))327		return -EINVAL;328 329	*status = 0;330 331	if (!psp || !psp->tee_data)332		return -ENODEV;333 334	if (psp_dead)335		return -EBUSY;336 337	tee = psp->tee_data;338 339	ret = tee_submit_cmd(tee, cmd_id, buf, len, &resp);340	if (ret)341		return ret;342 343	ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_RING_TIMEOUT);344	if (ret) {345		resp->flag = CMD_RESPONSE_TIMEDOUT;346		return ret;347	}348 349	memcpy(buf, &resp->buf[0], len);350	*status = resp->status;351 352	resp->flag = CMD_RESPONSE_COPIED;353 354	return 0;355}356EXPORT_SYMBOL(psp_tee_process_cmd);357 358int psp_check_tee_status(void)359{360	struct psp_device *psp = psp_get_master_device();361 362	if (!psp || !psp->tee_data)363		return -ENODEV;364 365	return 0;366}367EXPORT_SYMBOL(psp_check_tee_status);368