1 /* 2 * SRAM protect-exec region helper functions 3 * 4 * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ 5 * Dave Gerlach 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 * kind, whether express or implied; without even the implied warranty 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <linux/device.h> 18 #include <linux/genalloc.h> 19 #include <linux/sram.h> 20 21 #include <asm/cacheflush.h> 22 23 #include "sram.h" 24 25 static DEFINE_MUTEX(exec_pool_list_mutex); 26 static LIST_HEAD(exec_pool_list); 27 28 int sram_check_protect_exec(struct sram_dev *sram, struct sram_reserve *block, 29 struct sram_partition *part) 30 { 31 unsigned long base = (unsigned long)part->base; 32 unsigned long end = base + block->size; 33 34 if (!PAGE_ALIGNED(base) || !PAGE_ALIGNED(end)) { 35 dev_err(sram->dev, 36 "SRAM pool marked with 'protect-exec' is not page aligned and will not be created.\n"); 37 return -ENOMEM; 38 } 39 40 return 0; 41 } 42 43 int sram_add_protect_exec(struct sram_partition *part) 44 { 45 mutex_lock(&exec_pool_list_mutex); 46 list_add_tail(&part->list, &exec_pool_list); 47 mutex_unlock(&exec_pool_list_mutex); 48 49 return 0; 50 } 51 52 /** 53 * sram_exec_copy - copy data to a protected executable region of sram 54 * 55 * @pool: struct gen_pool retrieved that is part of this sram 56 * @dst: Destination address for the copy, that must be inside pool 57 * @src: Source address for the data to copy 58 * @size: Size of copy to perform, which starting from dst, must reside in pool 59 * 60 * This helper function allows sram driver to act as central control location 61 * of 'protect-exec' pools which are normal sram pools but are always set 62 * read-only and executable except when copying data to them, at which point 63 * they are set to read-write non-executable, to make sure no memory is 64 * writeable and executable at the same time. This region must be page-aligned 65 * and is checked during probe, otherwise page attribute manipulation would 66 * not be possible. 67 */ 68 int sram_exec_copy(struct gen_pool *pool, void *dst, void *src, 69 size_t size) 70 { 71 struct sram_partition *part = NULL, *p; 72 unsigned long base; 73 int pages; 74 75 mutex_lock(&exec_pool_list_mutex); 76 list_for_each_entry(p, &exec_pool_list, list) { 77 if (p->pool == pool) 78 part = p; 79 } 80 mutex_unlock(&exec_pool_list_mutex); 81 82 if (!part) 83 return -EINVAL; 84 85 if (!addr_in_gen_pool(pool, (unsigned long)dst, size)) 86 return -EINVAL; 87 88 base = (unsigned long)part->base; 89 pages = PAGE_ALIGN(size) / PAGE_SIZE; 90 91 mutex_lock(&part->lock); 92 93 set_memory_nx((unsigned long)base, pages); 94 set_memory_rw((unsigned long)base, pages); 95 96 memcpy(dst, src, size); 97 98 set_memory_ro((unsigned long)base, pages); 99 set_memory_x((unsigned long)base, pages); 100 101 mutex_unlock(&part->lock); 102 103 return 0; 104 } 105 EXPORT_SYMBOL_GPL(sram_exec_copy); 106