aboutsummaryrefslogtreecommitdiff
path: root/drivers/soc/qcom/kernel_protect.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/qcom/kernel_protect.c')
-rw-r--r--drivers/soc/qcom/kernel_protect.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/soc/qcom/kernel_protect.c b/drivers/soc/qcom/kernel_protect.c
index 73192971..b48cd0bf 100644
--- a/drivers/soc/qcom/kernel_protect.c
+++ b/drivers/soc/qcom/kernel_protect.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015,2016 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
@@ -14,10 +14,12 @@
#include <linux/printk.h>
#include <linux/init.h>
#include <linux/gfp.h>
+#include <soc/qcom/scm.h>
#include <soc/qcom/secure_buffer.h>
#include <asm/sections.h>
#include <asm/cacheflush.h>
+#define KERNEL_PROTECT_MPU 0x24
#ifdef CONFIG_MSM_KERNEL_PROTECT_TEST
@@ -38,6 +40,10 @@ static void msm_protect_kernel_test(void)
*/
char *addr = (char *)__alloc_pages_nodemask;
+ if (IS_ENABLED(CONFIG_MSM_KERNEL_PROTECT_MPU)) {
+ pr_err("MPU protected kernel code is HLOS writable\n");
+ return;
+ }
pr_err("Checking whether the kernel text is writable...\n");
pr_err("A BUG means it is writable (this is bad)\n");
pr_err("A stage-2 fault means it's not writable (this is good, but we'll still crash)\n");
@@ -84,9 +90,33 @@ static int __init msm_protect_kernel(void)
pr_debug("assigning from phys: %pa to %pa\n",
&kernel_x_start_rounded, &kernel_x_end);
pr_debug("virtual: %p to %p\n", virt_start, virt_end);
- ret = hyp_assign_phys(kernel_x_start_rounded,
- kernel_x_end - kernel_x_start_rounded,
- &vmid_hlos, 1, &vmid_hlos, &dest_perms, 1);
+
+ if (IS_ENABLED(CONFIG_MSM_KERNEL_PROTECT_MPU)) {
+ struct scm_desc desc = {0};
+
+ if (!scm_is_call_available(SCM_SVC_MP, KERNEL_PROTECT_MPU))
+ return 0;
+
+ desc.args[0] = kernel_x_start_rounded;
+ desc.args[1] = kernel_x_end - kernel_x_start_rounded;
+ desc.arginfo = SCM_ARGS(2);
+
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ KERNEL_PROTECT_MPU), &desc);
+ if (ret) {
+ /*
+ * must not proceed if failed to MPU protect kernel
+ * text region
+ */
+ panic("Failed to protect kernel region %pa -- %pa\n",
+ &kernel_x_start_rounded,
+ &kernel_x_end);
+ }
+ } else {
+ ret = hyp_assign_phys(kernel_x_start_rounded,
+ kernel_x_end - kernel_x_start_rounded,
+ &vmid_hlos, 1, &vmid_hlos, &dest_perms, 1);
+ }
if (ret)
/*
* We want to fail relatively silently since not all