Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ccp - provide in-kernel API to submit TEE commands

Extend the functionality of AMD Secure Processor (SP) driver by
providing an in-kernel API to submit commands to TEE ring buffer for
processing by Trusted OS running on AMD Secure Processor.

Following TEE commands are supported by Trusted OS:

* TEE_CMD_ID_LOAD_TA : Load Trusted Application (TA) binary into
TEE environment
* TEE_CMD_ID_UNLOAD_TA : Unload TA binary from TEE environment
* TEE_CMD_ID_OPEN_SESSION : Open session with loaded TA
* TEE_CMD_ID_CLOSE_SESSION : Close session with loaded TA
* TEE_CMD_ID_INVOKE_CMD : Invoke a command with loaded TA
* TEE_CMD_ID_MAP_SHARED_MEM : Map shared memory
* TEE_CMD_ID_UNMAP_SHARED_MEM : Unmap shared memory

Linux AMD-TEE driver will use this API to submit command buffers
for processing in Trusted Execution Environment. The AMD-TEE driver
shall be introduced in a separate patch.

Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Co-developed-by: Devaraj Rangasamy <Devaraj.Rangasamy@amd.com>
Signed-off-by: Devaraj Rangasamy <Devaraj.Rangasamy@amd.com>
Signed-off-by: Rijo Thomas <Rijo-john.Thomas@amd.com>
Acked-by: Gary R Hook <gary.hook@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Rijo Thomas and committed by
Herbert Xu
632b0b53 33960acc

+200
+126
drivers/crypto/ccp/tee-dev.c
··· 14 14 #include <linux/slab.h> 15 15 #include <linux/gfp.h> 16 16 #include <linux/psp-sev.h> 17 + #include <linux/psp-tee.h> 17 18 18 19 #include "psp-dev.h" 19 20 #include "tee-dev.h" ··· 39 38 rb_mgr->ring_start = start_addr; 40 39 rb_mgr->ring_size = ring_size; 41 40 rb_mgr->ring_pa = __psp_pa(start_addr); 41 + mutex_init(&rb_mgr->mutex); 42 42 43 43 return 0; 44 44 } ··· 57 55 rb_mgr->ring_start = NULL; 58 56 rb_mgr->ring_size = 0; 59 57 rb_mgr->ring_pa = 0; 58 + mutex_destroy(&rb_mgr->mutex); 60 59 } 61 60 62 61 static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout, ··· 239 236 240 237 tee_destroy_ring(tee); 241 238 } 239 + 240 + static int tee_submit_cmd(struct psp_tee_device *tee, enum tee_cmd_id cmd_id, 241 + void *buf, size_t len, struct tee_ring_cmd **resp) 242 + { 243 + struct tee_ring_cmd *cmd; 244 + u32 rptr, wptr; 245 + int nloop = 1000, ret = 0; 246 + 247 + *resp = NULL; 248 + 249 + mutex_lock(&tee->rb_mgr.mutex); 250 + 251 + wptr = tee->rb_mgr.wptr; 252 + 253 + /* Check if ring buffer is full */ 254 + do { 255 + rptr = ioread32(tee->io_regs + tee->vdata->ring_rptr_reg); 256 + 257 + if (!(wptr + sizeof(struct tee_ring_cmd) == rptr)) 258 + break; 259 + 260 + dev_info(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n", 261 + rptr, wptr); 262 + 263 + /* Wait if ring buffer is full */ 264 + mutex_unlock(&tee->rb_mgr.mutex); 265 + schedule_timeout_interruptible(msecs_to_jiffies(10)); 266 + mutex_lock(&tee->rb_mgr.mutex); 267 + 268 + } while (--nloop); 269 + 270 + if (!nloop && (wptr + sizeof(struct tee_ring_cmd) == rptr)) { 271 + dev_err(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u\n", 272 + rptr, wptr); 273 + ret = -EBUSY; 274 + goto unlock; 275 + } 276 + 277 + /* Pointer to empty data entry in ring buffer */ 278 + cmd = (struct tee_ring_cmd *)(tee->rb_mgr.ring_start + wptr); 279 + 280 + /* Write command data into ring buffer */ 281 + cmd->cmd_id = cmd_id; 282 + cmd->cmd_state = TEE_CMD_STATE_INIT; 283 + memset(&cmd->buf[0], 0, sizeof(cmd->buf)); 284 + memcpy(&cmd->buf[0], buf, len); 285 + 286 + /* Update local copy of write pointer */ 287 + tee->rb_mgr.wptr += sizeof(struct tee_ring_cmd); 288 + if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size) 289 + tee->rb_mgr.wptr = 0; 290 + 291 + /* Trigger interrupt to Trusted OS */ 292 + iowrite32(tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg); 293 + 294 + /* The response is provided by Trusted OS in same 295 + * location as submitted data entry within ring buffer. 296 + */ 297 + *resp = cmd; 298 + 299 + unlock: 300 + mutex_unlock(&tee->rb_mgr.mutex); 301 + 302 + return ret; 303 + } 304 + 305 + static int tee_wait_cmd_completion(struct psp_tee_device *tee, 306 + struct tee_ring_cmd *resp, 307 + unsigned int timeout) 308 + { 309 + /* ~5ms sleep per loop => nloop = timeout * 200 */ 310 + int nloop = timeout * 200; 311 + 312 + while (--nloop) { 313 + if (resp->cmd_state == TEE_CMD_STATE_COMPLETED) 314 + return 0; 315 + 316 + usleep_range(5000, 5100); 317 + } 318 + 319 + dev_err(tee->dev, "tee: command 0x%x timed out, disabling PSP\n", 320 + resp->cmd_id); 321 + 322 + psp_dead = true; 323 + 324 + return -ETIMEDOUT; 325 + } 326 + 327 + int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len, 328 + u32 *status) 329 + { 330 + struct psp_device *psp = psp_get_master_device(); 331 + struct psp_tee_device *tee; 332 + struct tee_ring_cmd *resp; 333 + int ret; 334 + 335 + if (!buf || !status || !len || len > sizeof(resp->buf)) 336 + return -EINVAL; 337 + 338 + *status = 0; 339 + 340 + if (!psp || !psp->tee_data) 341 + return -ENODEV; 342 + 343 + if (psp_dead) 344 + return -EBUSY; 345 + 346 + tee = psp->tee_data; 347 + 348 + ret = tee_submit_cmd(tee, cmd_id, buf, len, &resp); 349 + if (ret) 350 + return ret; 351 + 352 + ret = tee_wait_cmd_completion(tee, resp, TEE_DEFAULT_TIMEOUT); 353 + if (ret) 354 + return ret; 355 + 356 + memcpy(buf, &resp->buf[0], len); 357 + *status = resp->status; 358 + 359 + return 0; 360 + } 361 + EXPORT_SYMBOL(psp_tee_process_cmd);
+1
drivers/crypto/ccp/tee-dev.h
··· 54 54 * @wptr: index to the last written entry in ring buffer 55 55 */ 56 56 struct ring_buf_manager { 57 + struct mutex mutex; /* synchronizes access to ring buffer */ 57 58 void *ring_start; 58 59 u32 ring_size; 59 60 phys_addr_t ring_pa;
+73
include/linux/psp-tee.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * AMD Trusted Execution Environment (TEE) interface 4 + * 5 + * Author: Rijo Thomas <Rijo-john.Thomas@amd.com> 6 + * 7 + * Copyright 2019 Advanced Micro Devices, Inc. 8 + * 9 + */ 10 + 11 + #ifndef __PSP_TEE_H_ 12 + #define __PSP_TEE_H_ 13 + 14 + #include <linux/types.h> 15 + #include <linux/errno.h> 16 + 17 + /* This file defines the Trusted Execution Environment (TEE) interface commands 18 + * and the API exported by AMD Secure Processor driver to communicate with 19 + * AMD-TEE Trusted OS. 20 + */ 21 + 22 + /** 23 + * enum tee_cmd_id - TEE Interface Command IDs 24 + * @TEE_CMD_ID_LOAD_TA: Load Trusted Application (TA) binary into 25 + * TEE environment 26 + * @TEE_CMD_ID_UNLOAD_TA: Unload TA binary from TEE environment 27 + * @TEE_CMD_ID_OPEN_SESSION: Open session with loaded TA 28 + * @TEE_CMD_ID_CLOSE_SESSION: Close session with loaded TA 29 + * @TEE_CMD_ID_INVOKE_CMD: Invoke a command with loaded TA 30 + * @TEE_CMD_ID_MAP_SHARED_MEM: Map shared memory 31 + * @TEE_CMD_ID_UNMAP_SHARED_MEM: Unmap shared memory 32 + */ 33 + enum tee_cmd_id { 34 + TEE_CMD_ID_LOAD_TA = 1, 35 + TEE_CMD_ID_UNLOAD_TA, 36 + TEE_CMD_ID_OPEN_SESSION, 37 + TEE_CMD_ID_CLOSE_SESSION, 38 + TEE_CMD_ID_INVOKE_CMD, 39 + TEE_CMD_ID_MAP_SHARED_MEM, 40 + TEE_CMD_ID_UNMAP_SHARED_MEM, 41 + }; 42 + 43 + #ifdef CONFIG_CRYPTO_DEV_SP_PSP 44 + /** 45 + * psp_tee_process_cmd() - Process command in Trusted Execution Environment 46 + * @cmd_id: TEE command ID (&enum tee_cmd_id) 47 + * @buf: Command buffer for TEE processing. On success, is updated 48 + * with the response 49 + * @len: Length of command buffer in bytes 50 + * @status: On success, holds the TEE command execution status 51 + * 52 + * This function submits a command to the Trusted OS for processing in the 53 + * TEE environment and waits for a response or until the command times out. 54 + * 55 + * Returns: 56 + * 0 if TEE successfully processed the command 57 + * -%ENODEV if PSP device not available 58 + * -%EINVAL if invalid input 59 + * -%ETIMEDOUT if TEE command timed out 60 + * -%EBUSY if PSP device is not responsive 61 + */ 62 + int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, size_t len, 63 + u32 *status); 64 + 65 + #else /* !CONFIG_CRYPTO_DEV_SP_PSP */ 66 + 67 + static inline int psp_tee_process_cmd(enum tee_cmd_id cmd_id, void *buf, 68 + size_t len, u32 *status) 69 + { 70 + return -ENODEV; 71 + } 72 + #endif /* CONFIG_CRYPTO_DEV_SP_PSP */ 73 + #endif /* __PSP_TEE_H_ */