scm-mpu: Add additional memory protection options
Add support for a scm call to protect a contiguous physical address range. Add a config option to use this api to protect the kernel text section. Otherwise, the user may specify the region through module parameters. Change-Id: Ie751ec72deb1a1692093559fe8c6784e8bf912a2 Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
This commit is contained in:
parent
a28599fb04
commit
0eb2dddc23
|
@ -0,0 +1,36 @@
|
|||
Introduction
|
||||
============
|
||||
|
||||
The scm-mpu driver allows enabling xpu protection of arbitrary physical memory
|
||||
addresses as a debug mechanism.
|
||||
|
||||
Software description
|
||||
====================
|
||||
|
||||
Several methods of controlling this feature are provided.
|
||||
|
||||
* CONFIG_KERNEL_TEXT_MPU_PROT - Enables protection of the kernel code and
|
||||
read-only sections by default.
|
||||
|
||||
* kernel command line
|
||||
scm_mpu.mpu_start=0x0
|
||||
scm_mpu.mpu_size=0x1000
|
||||
|
||||
* /sys/module/scm_mpu/parameters
|
||||
echo 0x0 > mpu_start
|
||||
echo 0x1000 > mpu_size
|
||||
echo 0x11 > mpu_enable
|
||||
|
||||
The sysfs interface may also be used to unlock previously defined regions.
|
||||
echo 0x0 > mpu_start
|
||||
echo 0x1000 > mpu_size
|
||||
echo 0x10 > mpu_enable
|
||||
|
||||
Limitations
|
||||
===========
|
||||
The number of distinct regions allowed is limited by available resources.
|
||||
|
||||
No provisions are made for "carving out" or otherwise removing xpu protected
|
||||
regions from the linux memory map.
|
||||
|
||||
XPU protection currently uses 4K alignment.
|
|
@ -635,6 +635,14 @@ config QCOM_NPA_DUMP
|
|||
help
|
||||
Read the NPA dump from RPM memory through debugfs.
|
||||
|
||||
config KERNEL_TEXT_MPU_PROT
|
||||
bool "Enable xpu protection of kernel r/o sections"
|
||||
help
|
||||
Enables xpu protection of kernel code and read-only data
|
||||
sections early in boot. Read access is permitted to
|
||||
all masters; Write access is only permited to the
|
||||
secure world.
|
||||
|
||||
source "drivers/soc/qcom/memshare/Kconfig"
|
||||
|
||||
endif # ARCH_MSM
|
||||
|
|
|
@ -39,7 +39,7 @@ obj-$(CONFIG_MSM_QMI_INTERFACE) += qmi_interface.o
|
|||
|
||||
obj-$(CONFIG_MSM_CACHE_DUMP) += cache_dump.o
|
||||
obj-$(CONFIG_MSM_CPUSS_DUMP) += cpuss_dump.o
|
||||
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
|
||||
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o scm-mpu.o
|
||||
|
||||
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o smd_private.o smd_init_dt.o smsm_debug.o
|
||||
obj-$(CONFIG_MSM_SMEM) += smem.o smem_debug.o
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <soc/qcom/scm.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/sections.h>
|
||||
|
||||
#define TZ_PROTECT_MEMORY 0x1
|
||||
|
||||
/* filesystem parameters */
|
||||
#define MPU_MAGIC_LOCK 0x11
|
||||
#define MPU_MAGIC_UNLOCK 0x10
|
||||
|
||||
static ulong mpu_start;
|
||||
static ulong mpu_size;
|
||||
static u32 mpu_enable;
|
||||
|
||||
module_param(mpu_start, ulong, 0644);
|
||||
module_param(mpu_size, ulong, 0644);
|
||||
|
||||
static void mem_prot_region(u64 start, u64 size, bool lock);
|
||||
static int set_enabled(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = param_set_int(val, kp);
|
||||
|
||||
if (mpu_enable == MPU_MAGIC_LOCK)
|
||||
mem_prot_region(mpu_start, mpu_size, true);
|
||||
else if (mpu_enable == MPU_MAGIC_UNLOCK)
|
||||
mem_prot_region(mpu_start, mpu_size, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct kernel_param_ops mpu_ops = {
|
||||
.set = set_enabled,
|
||||
.get = param_get_int,
|
||||
};
|
||||
module_param_cb(mpu_enable, &mpu_ops, &mpu_enable, 0644);
|
||||
|
||||
static void mem_prot_region(u64 start, u64 size, bool lock)
|
||||
{
|
||||
int ret;
|
||||
struct scm_desc desc = {0};
|
||||
|
||||
desc.arginfo = SCM_ARGS(5);
|
||||
desc.args[0] = PAGE_ALIGN(start);
|
||||
desc.args[1] = PAGE_ALIGN(size);
|
||||
/*
|
||||
* Permissions: Write: Read
|
||||
* 0x1 TZ Anyone
|
||||
* 0x2 TZ Tz, APPS
|
||||
* 0x3 TZ Tz
|
||||
*/
|
||||
desc.args[2] = 0x1;
|
||||
desc.args[3] = lock;
|
||||
desc.args[4] = 0;
|
||||
|
||||
if (!is_scm_armv8())
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, TZ_PROTECT_MEMORY),
|
||||
&desc);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to %s region %llx - %llx\n",
|
||||
lock ? "protect" : "unlock", start, start + size);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KERNEL_TEXT_MPU_PROT
|
||||
static int __init mem_prot_init(void)
|
||||
{
|
||||
phys_addr_t phys = virt_to_phys(_stext);
|
||||
mem_prot_region((u64)phys, (u64)(_etext - _stext), true);
|
||||
return 0;
|
||||
}
|
||||
late_initcall(mem_prot_init);
|
||||
#else
|
||||
static int __init mem_prot_init(void)
|
||||
{
|
||||
if (mpu_start && mpu_size)
|
||||
mem_prot_region(mpu_start, mpu_size, true);
|
||||
return 0;
|
||||
}
|
||||
late_initcall(mem_prot_init);
|
||||
#endif
|
Loading…
Reference in New Issue