Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * SRAM protect-exec region helper functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *	Dave Gerlach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * it under the terms of the GNU General Public License version 2 as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * kind, whether express or implied; without even the implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/genalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/sram.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/fncpy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <asm/set_memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include "sram.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static DEFINE_MUTEX(exec_pool_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static LIST_HEAD(exec_pool_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) int sram_check_protect_exec(struct sram_dev *sram, struct sram_reserve *block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 			    struct sram_partition *part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	unsigned long base = (unsigned long)part->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	unsigned long end = base + block->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	if (!PAGE_ALIGNED(base) || !PAGE_ALIGNED(end)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		dev_err(sram->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 			"SRAM pool marked with 'protect-exec' is not page aligned and will not be created.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) int sram_add_protect_exec(struct sram_partition *part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	mutex_lock(&exec_pool_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	list_add_tail(&part->list, &exec_pool_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	mutex_unlock(&exec_pool_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * sram_exec_copy - copy data to a protected executable region of sram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * @pool: struct gen_pool retrieved that is part of this sram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * @dst: Destination address for the copy, that must be inside pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * @src: Source address for the data to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * @size: Size of copy to perform, which starting from dst, must reside in pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * Return: Address for copied data that can safely be called through function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *	   pointer, or NULL if problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * This helper function allows sram driver to act as central control location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * of 'protect-exec' pools which are normal sram pools but are always set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * read-only and executable except when copying data to them, at which point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * they are set to read-write non-executable, to make sure no memory is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * writeable and executable at the same time. This region must be page-aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * and is checked during probe, otherwise page attribute manipulation would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * not be possible. Care must be taken to only call the returned address as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * dst address is not guaranteed to be safely callable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * NOTE: This function uses the fncpy macro to move code to the executable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * region. Some architectures have strict requirements for relocating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * executable code, so fncpy is a macro that must be defined by any arch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * making use of this functionality that guarantees a safe copy of exec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * data and returns a safe address that can be called as a C function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		     size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	struct sram_partition *part = NULL, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	int pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	void *dst_cpy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	mutex_lock(&exec_pool_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	list_for_each_entry(p, &exec_pool_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		if (p->pool == pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			part = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	mutex_unlock(&exec_pool_list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	if (!part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (!gen_pool_has_addr(pool, (unsigned long)dst, size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	base = (unsigned long)part->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	pages = PAGE_ALIGN(size) / PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	mutex_lock(&part->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	ret = set_memory_nx((unsigned long)base, pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	ret = set_memory_rw((unsigned long)base, pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	dst_cpy = fncpy(dst, src, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	ret = set_memory_ro((unsigned long)base, pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	ret = set_memory_x((unsigned long)base, pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	mutex_unlock(&part->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	return dst_cpy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	mutex_unlock(&part->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) EXPORT_SYMBOL_GPL(sram_exec_copy);