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:
Patrick Daly 2015-05-05 14:09:01 -07:00
parent 5f451e1a25
commit 9ced33893e
2 changed files with 53 additions and 4 deletions

View File

@ -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);

View File

@ -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