soc: qcom: scm-mpu: Add an API to unlock the kernel text region
The cpaccess driver writes to the kernel text section during normal operation. Add an API to disable any protection of this region by the scm-mpu driver. Protection is not reenabled after cpaccess operations since this is expected to be an uncommon usecase. Change-Id: I83caa906b94f4a522a203c1170f1d913681fc704 Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
This commit is contained in:
parent
5f451e1a25
commit
9ced33893e
|
@ -14,6 +14,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <soc/qcom/scm.h>
|
||||
#include <soc/qcom/scm-mpu.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/sections.h>
|
||||
|
@ -33,11 +34,12 @@
|
|||
static ulong mpu_start;
|
||||
static ulong mpu_size;
|
||||
static u32 mpu_enable;
|
||||
/* Some drivers write to the kernel text area by design */
|
||||
static bool kernel_text_protected;
|
||||
|
||||
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;
|
||||
|
@ -56,7 +58,7 @@ static struct kernel_param_ops mpu_ops = {
|
|||
};
|
||||
module_param_cb(mpu_enable, &mpu_ops, &mpu_enable, 0644);
|
||||
|
||||
static void mem_prot_region(u64 start, u64 size, bool lock)
|
||||
int mem_prot_region(u64 start, u64 size, bool lock)
|
||||
{
|
||||
int ret;
|
||||
struct scm_desc desc = {0};
|
||||
|
@ -82,13 +84,30 @@ static void mem_prot_region(u64 start, u64 size, bool lock)
|
|||
if (ret != 0)
|
||||
pr_err("Failed to %s region %llx - %llx\n",
|
||||
lock ? "protect" : "unlock", start, start + size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void scm_mpu_unlock_kernel_text(void)
|
||||
{
|
||||
phys_addr_t phys = virt_to_phys(_stext);
|
||||
if (!kernel_text_protected)
|
||||
return;
|
||||
kernel_text_protected = false;
|
||||
mem_prot_region((u64)phys, (u64)(_etext - _stext), false);
|
||||
}
|
||||
|
||||
void scm_mpu_lock_kernel_text(void)
|
||||
{
|
||||
int ret;
|
||||
phys_addr_t phys = virt_to_phys(_stext);
|
||||
ret = mem_prot_region((u64)phys, (u64)(_etext - _stext), true);
|
||||
kernel_text_protected = !ret;
|
||||
}
|
||||
|
||||
#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);
|
||||
scm_mpu_lock_kernel_text();
|
||||
return 0;
|
||||
}
|
||||
late_initcall(mem_prot_init);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* 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.
|
||||
*/
|
||||
#ifndef __SCM_MPU_H
|
||||
#define __SCM_MPU_H
|
||||
|
||||
#ifdef CONFIG_MSM_SCM
|
||||
void scm_mpu_unlock_kernel_text(void);
|
||||
void scm_mpu_lock_kernel_text(void);
|
||||
|
||||
int mem_prot_region(u64 start, u64 size, bool lock);
|
||||
#else
|
||||
static inline void scm_mpu_unlock_kernel_text(void) {}
|
||||
static inline void scm_mpu_lock_kernel_text(void) {}
|
||||
|
||||
int mem_prot_region(u64 start, u64 size, bool lock)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue