summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/app_api.h7
-rw-r--r--arch/arm64/kernel/app_api.c35
-rw-r--r--arch/arm64/kernel/app_setting.c15
-rw-r--r--kernel/sched/core.c3
4 files changed, 60 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/app_api.h b/arch/arm64/include/asm/app_api.h
index 2162400fde13..7032d636dab6 100644
--- a/arch/arm64/include/asm/app_api.h
+++ b/arch/arm64/include/asm/app_api.h
@@ -27,16 +27,23 @@
#ifdef CONFIG_MSM_APP_API
extern void set_app_setting_bit(uint32_t bit);
extern void clear_app_setting_bit(uint32_t bit);
+extern void set_app_setting_bit_for_32bit_apps(void);
+extern void clear_app_setting_bit_for_32bit_apps(void);
#else
static inline void set_app_setting_bit(uint32_t bit) {}
static inline void clear_app_setting_bit(uint32_t bit) {}
+static inline void set_app_setting_bit_for_32bit_apps(void) {}
+static inline void clear_app_setting_bit_for_32bit_apps(void) {}
#endif
#ifdef CONFIG_MSM_APP_SETTINGS
extern void switch_app_setting_bit(struct task_struct *prev,
struct task_struct *next);
+extern void switch_32bit_app_setting_bit(struct task_struct *prev,
+ struct task_struct *next);
extern void apply_app_setting_bit(struct file *file);
extern bool use_app_setting;
+extern bool use_32bit_app_setting;
#endif
#endif
diff --git a/arch/arm64/kernel/app_api.c b/arch/arm64/kernel/app_api.c
index 39eeee1a9029..1b3732accd4b 100644
--- a/arch/arm64/kernel/app_api.c
+++ b/arch/arm64/kernel/app_api.c
@@ -18,6 +18,7 @@
#include <asm/app_api.h>
static spinlock_t spinlock;
+static spinlock_t spinlock_32bit_app;
static DEFINE_PER_CPU(int, app_config_applied);
static unsigned long app_config_set[NR_CPUS];
static unsigned long app_config_clear[NR_CPUS];
@@ -67,9 +68,43 @@ void clear_app_setting_bit(uint32_t bit)
}
EXPORT_SYMBOL(clear_app_setting_bit);
+void set_app_setting_bit_for_32bit_apps(void)
+{
+ unsigned long flags;
+ uint64_t reg;
+
+ spin_lock_irqsave(&spinlock_32bit_app, flags);
+ asm volatile("mrs %0, S3_0_c15_c15_1 " : "=r" (reg));
+ reg = reg | BIT(18);
+ reg = reg & ~BIT(2);
+ reg = reg | 0x3;
+ isb();
+ asm volatile("msr S3_0_c15_c15_1, %0" : : "r" (reg));
+ isb();
+ spin_unlock_irqrestore(&spinlock_32bit_app, flags);
+}
+EXPORT_SYMBOL(set_app_setting_bit_for_32bit_apps);
+
+void clear_app_setting_bit_for_32bit_apps(void)
+{
+ unsigned long flags;
+ uint64_t reg;
+
+ spin_lock_irqsave(&spinlock_32bit_app, flags);
+ asm volatile("mrs %0, S3_0_c15_c15_1 " : "=r" (reg));
+ reg = reg & ~BIT(18);
+ reg = reg & ~0x3;
+ isb();
+ asm volatile("msr S3_0_c15_c15_1, %0" : : "r" (reg));
+ isb();
+ spin_unlock_irqrestore(&spinlock_32bit_app, flags);
+}
+EXPORT_SYMBOL(clear_app_setting_bit_for_32bit_apps);
+
static int __init init_app_api(void)
{
spin_lock_init(&spinlock);
+ spin_lock_init(&spinlock_32bit_app);
return 0;
}
early_initcall(init_app_api);
diff --git a/arch/arm64/kernel/app_setting.c b/arch/arm64/kernel/app_setting.c
index 6b4eb28d0e24..8e7aeab39edd 100644
--- a/arch/arm64/kernel/app_setting.c
+++ b/arch/arm64/kernel/app_setting.c
@@ -35,6 +35,10 @@ bool use_app_setting = true;
module_param(use_app_setting, bool, 0644);
MODULE_PARM_DESC(use_app_setting, "control use of app specific settings");
+bool use_32bit_app_setting = true;
+module_param(use_32bit_app_setting, bool, 0644);
+MODULE_PARM_DESC(use_32bit_app_setting, "control use of 32 bit app specific settings");
+
static int set_name(const char *str, struct kernel_param *kp)
{
int len = strlen(str);
@@ -87,6 +91,17 @@ void switch_app_setting_bit(struct task_struct *prev, struct task_struct *next)
}
EXPORT_SYMBOL(switch_app_setting_bit);
+void switch_32bit_app_setting_bit(struct task_struct *prev,
+ struct task_struct *next)
+{
+ if (prev->mm && unlikely(is_compat_thread(task_thread_info(prev))))
+ clear_app_setting_bit_for_32bit_apps();
+
+ if (next->mm && unlikely(is_compat_thread(task_thread_info(next))))
+ set_app_setting_bit_for_32bit_apps();
+}
+EXPORT_SYMBOL(switch_32bit_app_setting_bit);
+
void apply_app_setting_bit(struct file *file)
{
bool found = false;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 699008696da8..d6e7a1d7168d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2729,6 +2729,9 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
#ifdef CONFIG_MSM_APP_SETTINGS
if (use_app_setting)
switch_app_setting_bit(prev, next);
+
+ if (use_32bit_app_setting)
+ switch_32bit_app_setting_bit(prev, next);
#endif
}