/* We need actual physical address instead of DMA address, since *TrustedOSrunningonAMDSecureProcessorwillmapthisregion
*/
start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size)); if (!start_addr) return -ENOMEM;
ret = tee_alloc_ring(tee, ring_size); if (ret) {
dev_err(tee->dev, "tee: ring allocation failed %d\n", ret); return ret;
}
tee->rb_mgr.wptr = 0;
cmd = tee_alloc_cmd_buffer(tee); if (!cmd) {
tee_free_ring(tee); return -ENOMEM;
}
/* Send command buffer details to Trusted OS by writing to *CPU-PSPmessageregisters
*/
ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,
TEE_DEFAULT_CMD_TIMEOUT, ®); if (ret) {
dev_err(tee->dev, "tee: ring init command timed out, disabling TEE support\n");
tee_free_ring(tee);
psp_dead = true; goto free_buf;
}
if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",
FIELD_GET(PSP_CMDRESP_STS, reg));
tee_free_ring(tee);
ret = -EIO;
}
free_buf:
tee_free_cmd_buffer(cmd);
return ret;
}
staticvoid tee_destroy_ring(struct psp_tee_device *tee)
{ unsignedint reg; int ret;
if (!tee->rb_mgr.ring_start) return;
if (psp_dead) goto free_ring;
ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL,
TEE_DEFAULT_CMD_TIMEOUT, ®); if (ret) {
dev_err(tee->dev, "tee: ring destroy command timed out, disabling TEE support\n");
psp_dead = true;
} elseif (FIELD_GET(PSP_CMDRESP_STS, reg)) {
dev_err(tee->dev, "tee: ring destroy command failed (%#010lx)\n",
FIELD_GET(PSP_CMDRESP_STS, reg));
}
free_ring:
tee_free_ring(tee);
}
int tee_dev_init(struct psp_device *psp)
{ struct device *dev = psp->dev; struct psp_tee_device *tee; int ret;
ret = -ENOMEM;
tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL); if (!tee) goto e_err;
psp->tee_data = tee;
tee->dev = dev;
tee->psp = psp;
tee->io_regs = psp->io_regs;
tee->vdata = (struct tee_vdata *)psp->vdata->tee; if (!tee->vdata) {
ret = -ENODEV;
dev_err(dev, "tee: missing driver data\n"); goto e_err;
}
ret = tee_init_ring(tee); if (ret) {
dev_err(dev, "tee: failed to init ring buffer\n"); goto e_err;
}
/* Loop until empty entry found in ring buffer */ do { /* Get pointer to ring buffer command entry */
cmd = (struct tee_ring_cmd *)
(tee->rb_mgr.ring_start + tee->rb_mgr.wptr);
/* Check if ring buffer is full or command entry is waiting *forresponsefromTEE
*/ if (!(tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||
cmd->flag == CMD_WAITING_FOR_RESPONSE)) break;
/* Wait if ring buffer is full or TEE is processing data */
mutex_unlock(&tee->rb_mgr.mutex);
schedule_timeout_interruptible(msecs_to_jiffies(10));
mutex_lock(&tee->rb_mgr.mutex);
} while (--nloop);
if (!nloop &&
(tee->rb_mgr.wptr + sizeof(struct tee_ring_cmd) == rptr ||
cmd->flag == CMD_WAITING_FOR_RESPONSE)) {
dev_err(tee->dev, "tee: ring buffer full. rptr = %u wptr = %u response flag %u\n",
rptr, tee->rb_mgr.wptr, cmd->flag);
ret = -EBUSY; goto unlock;
}
/* Do not submit command if PSP got disabled while processing any *commandinanotherthread
*/ if (psp_dead) {
ret = -EBUSY; goto unlock;
}
/* Write command data into ring buffer */
cmd->cmd_id = cmd_id;
cmd->cmd_state = TEE_CMD_STATE_INIT;
memset(&cmd->buf[0], 0, sizeof(cmd->buf));
memcpy(&cmd->buf[0], buf, len);
/* Indicate driver is waiting for response */
cmd->flag = CMD_WAITING_FOR_RESPONSE;
/* Update local copy of write pointer */
tee->rb_mgr.wptr += sizeof(struct tee_ring_cmd); if (tee->rb_mgr.wptr >= tee->rb_mgr.ring_size)
tee->rb_mgr.wptr = 0;
/* Trigger interrupt to Trusted OS */
iowrite32(tee->rb_mgr.wptr, tee->io_regs + tee->vdata->ring_wptr_reg);
/* The response is provided by Trusted OS in same *locationassubmitteddataentrywithinringbuffer.
*/
*resp = cmd;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.