aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tee/optee/core.c')
-rw-r--r--drivers/tee/optee/core.c180
1 files changed, 102 insertions, 78 deletions
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index b4fe7713b2fb..58169e519422 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -11,6 +11,10 @@
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 * 12 *
13 */ 13 */
14
15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17#include <linux/arm-smccc.h>
14#include <linux/errno.h> 18#include <linux/errno.h>
15#include <linux/io.h> 19#include <linux/io.h>
16#include <linux/module.h> 20#include <linux/module.h>
@@ -326,9 +330,8 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
326 * point of view) or not, is_smp() returns the the information 330 * point of view) or not, is_smp() returns the the information
327 * needed, but can't be called directly from here. 331 * needed, but can't be called directly from here.
328 */ 332 */
329#ifndef CONFIG_SMP 333 if (!IS_ENABLED(CONFIG_SMP) || nr_cpu_ids == 1)
330 a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR; 334 a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR;
331#endif
332 335
333 invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, a1, 0, 0, 0, 0, 0, 0, 336 invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, a1, 0, 0, 0, 0, 0, 0,
334 &res.smccc); 337 &res.smccc);
@@ -341,8 +344,7 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
341} 344}
342 345
343static struct tee_shm_pool * 346static struct tee_shm_pool *
344optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn, 347optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
345 void __iomem **ioremaped_shm)
346{ 348{
347 union { 349 union {
348 struct arm_smccc_res smccc; 350 struct arm_smccc_res smccc;
@@ -354,18 +356,18 @@ optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn,
354 size_t size; 356 size_t size;
355 phys_addr_t begin; 357 phys_addr_t begin;
356 phys_addr_t end; 358 phys_addr_t end;
357 void __iomem *va; 359 void *va;
358 struct tee_shm_pool_mem_info priv_info; 360 struct tee_shm_pool_mem_info priv_info;
359 struct tee_shm_pool_mem_info dmabuf_info; 361 struct tee_shm_pool_mem_info dmabuf_info;
360 362
361 invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); 363 invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
362 if (res.result.status != OPTEE_SMC_RETURN_OK) { 364 if (res.result.status != OPTEE_SMC_RETURN_OK) {
363 dev_info(dev, "shm service not available\n"); 365 pr_info("shm service not available\n");
364 return ERR_PTR(-ENOENT); 366 return ERR_PTR(-ENOENT);
365 } 367 }
366 368
367 if (res.result.settings != OPTEE_SMC_SHM_CACHED) { 369 if (res.result.settings != OPTEE_SMC_SHM_CACHED) {
368 dev_err(dev, "only normal cached shared memory supported\n"); 370 pr_err("only normal cached shared memory supported\n");
369 return ERR_PTR(-EINVAL); 371 return ERR_PTR(-EINVAL);
370 } 372 }
371 373
@@ -375,13 +377,13 @@ optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn,
375 size = end - begin; 377 size = end - begin;
376 378
377 if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) { 379 if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) {
378 dev_err(dev, "too small shared memory area\n"); 380 pr_err("too small shared memory area\n");
379 return ERR_PTR(-EINVAL); 381 return ERR_PTR(-EINVAL);
380 } 382 }
381 383
382 va = ioremap_cache(paddr, size); 384 va = memremap(paddr, size, MEMREMAP_WB);
383 if (!va) { 385 if (!va) {
384 dev_err(dev, "shared memory ioremap failed\n"); 386 pr_err("shared memory ioremap failed\n");
385 return ERR_PTR(-EINVAL); 387 return ERR_PTR(-EINVAL);
386 } 388 }
387 vaddr = (unsigned long)va; 389 vaddr = (unsigned long)va;
@@ -393,97 +395,112 @@ optee_config_shm_ioremap(struct device *dev, optee_invoke_fn *invoke_fn,
393 dmabuf_info.paddr = paddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; 395 dmabuf_info.paddr = paddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
394 dmabuf_info.size = size - OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; 396 dmabuf_info.size = size - OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
395 397
396 pool = tee_shm_pool_alloc_res_mem(dev, &priv_info, &dmabuf_info); 398 pool = tee_shm_pool_alloc_res_mem(&priv_info, &dmabuf_info);
397 if (IS_ERR(pool)) { 399 if (IS_ERR(pool)) {
398 iounmap(va); 400 memunmap(va);
399 goto out; 401 goto out;
400 } 402 }
401 403
402 *ioremaped_shm = va; 404 *memremaped_shm = va;
403out: 405out:
404 return pool; 406 return pool;
405} 407}
406 408
407static int get_invoke_func(struct device *dev, optee_invoke_fn **invoke_fn) 409/* Simple wrapper functions to be able to use a function pointer */
410static void optee_smccc_smc(unsigned long a0, unsigned long a1,
411 unsigned long a2, unsigned long a3,
412 unsigned long a4, unsigned long a5,
413 unsigned long a6, unsigned long a7,
414 struct arm_smccc_res *res)
415{
416 arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
417}
418
419static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
420 unsigned long a2, unsigned long a3,
421 unsigned long a4, unsigned long a5,
422 unsigned long a6, unsigned long a7,
423 struct arm_smccc_res *res)
424{
425 arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
426}
427
428static optee_invoke_fn *get_invoke_func(struct device_node *np)
408{ 429{
409 struct device_node *np = dev->of_node;
410 const char *method; 430 const char *method;
411 431
412 dev_info(dev, "probing for conduit method from DT.\n"); 432 pr_info("probing for conduit method from DT.\n");
413 433
414 if (of_property_read_string(np, "method", &method)) { 434 if (of_property_read_string(np, "method", &method)) {
415 dev_warn(dev, "missing \"method\" property\n"); 435 pr_warn("missing \"method\" property\n");
416 return -ENXIO; 436 return ERR_PTR(-ENXIO);
417 } 437 }
418 438
419 if (!strcmp("hvc", method)) { 439 if (!strcmp("hvc", method))
420 *invoke_fn = arm_smccc_hvc; 440 return optee_smccc_hvc;
421 } else if (!strcmp("smc", method)) { 441 else if (!strcmp("smc", method))
422 *invoke_fn = arm_smccc_smc; 442 return optee_smccc_smc;
423 } else { 443
424 dev_warn(dev, "invalid \"method\" property: %s\n", method); 444 pr_warn("invalid \"method\" property: %s\n", method);
425 return -EINVAL; 445 return ERR_PTR(-EINVAL);
426 }
427 return 0;
428} 446}
429 447
430static int optee_probe(struct platform_device *pdev) 448static struct optee *optee_probe(struct device_node *np)
431{ 449{
432 optee_invoke_fn *invoke_fn; 450 optee_invoke_fn *invoke_fn;
433 struct tee_shm_pool *pool; 451 struct tee_shm_pool *pool;
434 struct optee *optee = NULL; 452 struct optee *optee = NULL;
435 void __iomem *ioremaped_shm = NULL; 453 void *memremaped_shm = NULL;
436 struct tee_device *teedev; 454 struct tee_device *teedev;
437 u32 sec_caps; 455 u32 sec_caps;
438 int rc; 456 int rc;
439 457
440 rc = get_invoke_func(&pdev->dev, &invoke_fn); 458 invoke_fn = get_invoke_func(np);
441 if (rc) 459 if (IS_ERR(invoke_fn))
442 return rc; 460 return (void *)invoke_fn;
443 461
444 if (!optee_msg_api_uid_is_optee_api(invoke_fn)) { 462 if (!optee_msg_api_uid_is_optee_api(invoke_fn)) {
445 dev_warn(&pdev->dev, "api uid mismatch\n"); 463 pr_warn("api uid mismatch\n");
446 return -EINVAL; 464 return ERR_PTR(-EINVAL);
447 } 465 }
448 466
449 if (!optee_msg_api_revision_is_compatible(invoke_fn)) { 467 if (!optee_msg_api_revision_is_compatible(invoke_fn)) {
450 dev_warn(&pdev->dev, "api revision mismatch\n"); 468 pr_warn("api revision mismatch\n");
451 return -EINVAL; 469 return ERR_PTR(-EINVAL);
452 } 470 }
453 471
454 if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) { 472 if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) {
455 dev_warn(&pdev->dev, "capabilities mismatch\n"); 473 pr_warn("capabilities mismatch\n");
456 return -EINVAL; 474 return ERR_PTR(-EINVAL);
457 } 475 }
458 476
459 /* 477 /*
460 * We have no other option for shared memory, if secure world 478 * We have no other option for shared memory, if secure world
461 * doesn't have any reserved memory we can use we can't continue. 479 * doesn't have any reserved memory we can use we can't continue.
462 */ 480 */
463 if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVERED_SHM)) 481 if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
464 return -EINVAL; 482 return ERR_PTR(-EINVAL);
465 483
466 pool = optee_config_shm_ioremap(&pdev->dev, invoke_fn, &ioremaped_shm); 484 pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm);
467 if (IS_ERR(pool)) 485 if (IS_ERR(pool))
468 return PTR_ERR(pool); 486 return (void *)pool;
469 487
470 optee = devm_kzalloc(&pdev->dev, sizeof(*optee), GFP_KERNEL); 488 optee = kzalloc(sizeof(*optee), GFP_KERNEL);
471 if (!optee) { 489 if (!optee) {
472 rc = -ENOMEM; 490 rc = -ENOMEM;
473 goto err; 491 goto err;
474 } 492 }
475 493
476 optee->dev = &pdev->dev;
477 optee->invoke_fn = invoke_fn; 494 optee->invoke_fn = invoke_fn;
478 495
479 teedev = tee_device_alloc(&optee_desc, &pdev->dev, pool, optee); 496 teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
480 if (IS_ERR(teedev)) { 497 if (IS_ERR(teedev)) {
481 rc = PTR_ERR(teedev); 498 rc = PTR_ERR(teedev);
482 goto err; 499 goto err;
483 } 500 }
484 optee->teedev = teedev; 501 optee->teedev = teedev;
485 502
486 teedev = tee_device_alloc(&optee_supp_desc, &pdev->dev, pool, optee); 503 teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
487 if (IS_ERR(teedev)) { 504 if (IS_ERR(teedev)) {
488 rc = PTR_ERR(teedev); 505 rc = PTR_ERR(teedev);
489 goto err; 506 goto err;
@@ -502,15 +519,13 @@ static int optee_probe(struct platform_device *pdev)
502 INIT_LIST_HEAD(&optee->call_queue.waiters); 519 INIT_LIST_HEAD(&optee->call_queue.waiters);
503 optee_wait_queue_init(&optee->wait_queue); 520 optee_wait_queue_init(&optee->wait_queue);
504 optee_supp_init(&optee->supp); 521 optee_supp_init(&optee->supp);
505 optee->ioremaped_shm = ioremaped_shm; 522 optee->memremaped_shm = memremaped_shm;
506 optee->pool = pool; 523 optee->pool = pool;
507 524
508 platform_set_drvdata(pdev, optee);
509
510 optee_enable_shm_cache(optee); 525 optee_enable_shm_cache(optee);
511 526
512 dev_info(&pdev->dev, "initialized driver\n"); 527 pr_info("initialized driver\n");
513 return 0; 528 return optee;
514err: 529err:
515 if (optee) { 530 if (optee) {
516 /* 531 /*
@@ -520,18 +535,17 @@ err:
520 */ 535 */
521 tee_device_unregister(optee->supp_teedev); 536 tee_device_unregister(optee->supp_teedev);
522 tee_device_unregister(optee->teedev); 537 tee_device_unregister(optee->teedev);
538 kfree(optee);
523 } 539 }
524 if (pool) 540 if (pool)
525 tee_shm_pool_free(pool); 541 tee_shm_pool_free(pool);
526 if (ioremaped_shm) 542 if (memremaped_shm)
527 iounmap(ioremaped_shm); 543 memunmap(memremaped_shm);
528 return rc; 544 return ERR_PTR(rc);
529} 545}
530 546
531static int optee_remove(struct platform_device *pdev) 547static void optee_remove(struct optee *optee)
532{ 548{
533 struct optee *optee = platform_get_drvdata(pdev);
534
535 /* 549 /*
536 * Ask OP-TEE to free all cached shared memory objects to decrease 550 * Ask OP-TEE to free all cached shared memory objects to decrease
537 * reference counters and also avoid wild pointers in secure world 551 * reference counters and also avoid wild pointers in secure world
@@ -547,13 +561,13 @@ static int optee_remove(struct platform_device *pdev)
547 tee_device_unregister(optee->teedev); 561 tee_device_unregister(optee->teedev);
548 562
549 tee_shm_pool_free(optee->pool); 563 tee_shm_pool_free(optee->pool);
550 if (optee->ioremaped_shm) 564 if (optee->memremaped_shm)
551 iounmap(optee->ioremaped_shm); 565 memunmap(optee->memremaped_shm);
552 optee_wait_queue_exit(&optee->wait_queue); 566 optee_wait_queue_exit(&optee->wait_queue);
553 optee_supp_uninit(&optee->supp); 567 optee_supp_uninit(&optee->supp);
554 mutex_destroy(&optee->call_queue.mutex); 568 mutex_destroy(&optee->call_queue.mutex);
555 569
556 return 0; 570 kfree(optee);
557} 571}
558 572
559static const struct of_device_id optee_match[] = { 573static const struct of_device_id optee_match[] = {
@@ -561,33 +575,43 @@ static const struct of_device_id optee_match[] = {
561 {}, 575 {},
562}; 576};
563 577
564static struct platform_driver optee_driver = { 578static struct optee *optee_svc;
565 .driver = {
566 .name = DRIVER_NAME,
567 .of_match_table = optee_match,
568 },
569 .probe = optee_probe,
570 .remove = optee_remove,
571};
572 579
573static int __init optee_driver_init(void) 580static int __init optee_driver_init(void)
574{ 581{
575 struct device_node *node; 582 struct device_node *fw_np;
583 struct device_node *np;
584 struct optee *optee;
576 585
577 /* 586 /* Node is supposed to be below /firmware */
578 * Preferred path is /firmware/optee, but it's the matching that 587 fw_np = of_find_node_by_name(NULL, "firmware");
579 * matters. 588 if (!fw_np)
580 */ 589 return -ENODEV;
581 for_each_matching_node(node, optee_match) 590
582 of_platform_device_create(node, NULL, NULL); 591 np = of_find_matching_node(fw_np, optee_match);
592 of_node_put(fw_np);
593 if (!np)
594 return -ENODEV;
595
596 optee = optee_probe(np);
597 of_node_put(np);
598
599 if (IS_ERR(optee))
600 return PTR_ERR(optee);
583 601
584 return platform_driver_register(&optee_driver); 602 optee_svc = optee;
603
604 return 0;
585} 605}
586module_init(optee_driver_init); 606module_init(optee_driver_init);
587 607
588static void __exit optee_driver_exit(void) 608static void __exit optee_driver_exit(void)
589{ 609{
590 platform_driver_unregister(&optee_driver); 610 struct optee *optee = optee_svc;
611
612 optee_svc = NULL;
613 if (optee)
614 optee_remove(optee);
591} 615}
592module_exit(optee_driver_exit); 616module_exit(optee_driver_exit);
593 617