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

Configure Feed

Select the types of activity you want to include in your feed.

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