cc_fips.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (C) 2012-2018 ARM Limited or its affiliates. */
  3. #include <linux/kernel.h>
  4. #include <linux/fips.h>
  5. #include "cc_driver.h"
  6. #include "cc_fips.h"
  7. static void fips_dsr(unsigned long devarg);
  8. struct cc_fips_handle {
  9. struct tasklet_struct tasklet;
  10. };
  11. /* The function called once at driver entry point to check
  12. * whether TEE FIPS error occurred.
  13. */
  14. static bool cc_get_tee_fips_status(struct cc_drvdata *drvdata)
  15. {
  16. u32 reg;
  17. reg = cc_ioread(drvdata, CC_REG(GPR_HOST));
  18. return (reg == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK));
  19. }
  20. /*
  21. * This function should push the FIPS REE library status towards the TEE library
  22. * by writing the error state to HOST_GPR0 register.
  23. */
  24. void cc_set_ree_fips_status(struct cc_drvdata *drvdata, bool status)
  25. {
  26. int val = CC_FIPS_SYNC_REE_STATUS;
  27. if (drvdata->hw_rev < CC_HW_REV_712)
  28. return;
  29. val |= (status ? CC_FIPS_SYNC_MODULE_OK : CC_FIPS_SYNC_MODULE_ERROR);
  30. cc_iowrite(drvdata, CC_REG(HOST_GPR0), val);
  31. }
  32. void cc_fips_fini(struct cc_drvdata *drvdata)
  33. {
  34. struct cc_fips_handle *fips_h = drvdata->fips_handle;
  35. if (drvdata->hw_rev < CC_HW_REV_712 || !fips_h)
  36. return;
  37. /* Kill tasklet */
  38. tasklet_kill(&fips_h->tasklet);
  39. kfree(fips_h);
  40. drvdata->fips_handle = NULL;
  41. }
  42. void fips_handler(struct cc_drvdata *drvdata)
  43. {
  44. struct cc_fips_handle *fips_handle_ptr = drvdata->fips_handle;
  45. if (drvdata->hw_rev < CC_HW_REV_712)
  46. return;
  47. tasklet_schedule(&fips_handle_ptr->tasklet);
  48. }
  49. static inline void tee_fips_error(struct device *dev)
  50. {
  51. if (fips_enabled)
  52. panic("ccree: TEE reported cryptographic error in fips mode!\n");
  53. else
  54. dev_err(dev, "TEE reported error!\n");
  55. }
  56. /* Deferred service handler, run as interrupt-fired tasklet */
  57. static void fips_dsr(unsigned long devarg)
  58. {
  59. struct cc_drvdata *drvdata = (struct cc_drvdata *)devarg;
  60. struct device *dev = drvdata_to_dev(drvdata);
  61. u32 irq, state, val;
  62. irq = (drvdata->irq & (CC_GPR0_IRQ_MASK));
  63. if (irq) {
  64. state = cc_ioread(drvdata, CC_REG(GPR_HOST));
  65. if (state != (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK))
  66. tee_fips_error(dev);
  67. }
  68. /* after verifing that there is nothing to do,
  69. * unmask AXI completion interrupt.
  70. */
  71. val = (CC_REG(HOST_IMR) & ~irq);
  72. cc_iowrite(drvdata, CC_REG(HOST_IMR), val);
  73. }
  74. /* The function called once at driver entry point .*/
  75. int cc_fips_init(struct cc_drvdata *p_drvdata)
  76. {
  77. struct cc_fips_handle *fips_h;
  78. struct device *dev = drvdata_to_dev(p_drvdata);
  79. if (p_drvdata->hw_rev < CC_HW_REV_712)
  80. return 0;
  81. fips_h = kzalloc(sizeof(*fips_h), GFP_KERNEL);
  82. if (!fips_h)
  83. return -ENOMEM;
  84. p_drvdata->fips_handle = fips_h;
  85. dev_dbg(dev, "Initializing fips tasklet\n");
  86. tasklet_init(&fips_h->tasklet, fips_dsr, (unsigned long)p_drvdata);
  87. if (!cc_get_tee_fips_status(p_drvdata))
  88. tee_fips_error(dev);
  89. return 0;
  90. }