150 lines
4.4 KiB
Diff
150 lines
4.4 KiB
Diff
|
Subject: arm-enable-highmem-for-rt.patch
|
||
|
From: Thomas Gleixner <tglx@linutronix.de>
|
||
|
Date: Wed, 13 Feb 2013 11:03:11 +0100
|
||
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/3.10/patches-3.10.4-rt1.tar.xz
|
||
|
|
||
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||
|
---
|
||
|
arch/arm/Kconfig | 2 -
|
||
|
arch/arm/include/asm/switch_to.h | 9 ++++++++
|
||
|
arch/arm/mm/highmem.c | 41 +++++++++++++++++++++++++++++++++++++--
|
||
|
include/linux/highmem.h | 1
|
||
|
4 files changed, 50 insertions(+), 3 deletions(-)
|
||
|
|
||
|
Index: linux-stable/arch/arm/Kconfig
|
||
|
===================================================================
|
||
|
--- linux-stable.orig/arch/arm/Kconfig
|
||
|
+++ linux-stable/arch/arm/Kconfig
|
||
|
@@ -1704,7 +1704,7 @@ config HAVE_ARCH_PFN_VALID
|
||
|
|
||
|
config HIGHMEM
|
||
|
bool "High Memory Support"
|
||
|
- depends on MMU && !PREEMPT_RT_FULL
|
||
|
+ depends on MMU
|
||
|
help
|
||
|
The address space of ARM processors is only 4 Gigabytes large
|
||
|
and it has to accommodate user address space, kernel address
|
||
|
Index: linux-stable/arch/arm/include/asm/switch_to.h
|
||
|
===================================================================
|
||
|
--- linux-stable.orig/arch/arm/include/asm/switch_to.h
|
||
|
+++ linux-stable/arch/arm/include/asm/switch_to.h
|
||
|
@@ -3,6 +3,14 @@
|
||
|
|
||
|
#include <linux/thread_info.h>
|
||
|
|
||
|
+#if defined CONFIG_PREEMPT_RT_FULL && defined CONFIG_HIGHMEM
|
||
|
+void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p);
|
||
|
+#else
|
||
|
+static inline void
|
||
|
+switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) { }
|
||
|
+#endif
|
||
|
+
|
||
|
+
|
||
|
/*
|
||
|
* switch_to(prev, next) should switch from task `prev' to `next'
|
||
|
* `prev' will never be the same as `next'. schedule() itself
|
||
|
@@ -12,6 +20,7 @@ extern struct task_struct *__switch_to(s
|
||
|
|
||
|
#define switch_to(prev,next,last) \
|
||
|
do { \
|
||
|
+ switch_kmaps(prev, next); \
|
||
|
last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
|
||
|
} while (0)
|
||
|
|
||
|
Index: linux-stable/arch/arm/mm/highmem.c
|
||
|
===================================================================
|
||
|
--- linux-stable.orig/arch/arm/mm/highmem.c
|
||
|
+++ linux-stable/arch/arm/mm/highmem.c
|
||
|
@@ -38,6 +38,7 @@ EXPORT_SYMBOL(kunmap);
|
||
|
|
||
|
void *kmap_atomic(struct page *page)
|
||
|
{
|
||
|
+ pte_t pte = mk_pte(page, kmap_prot);
|
||
|
unsigned int idx;
|
||
|
unsigned long vaddr;
|
||
|
void *kmap;
|
||
|
@@ -76,7 +77,10 @@ void *kmap_atomic(struct page *page)
|
||
|
* in place, so the contained TLB flush ensures the TLB is updated
|
||
|
* with the new mapping.
|
||
|
*/
|
||
|
- set_top_pte(vaddr, mk_pte(page, kmap_prot));
|
||
|
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||
|
+ current->kmap_pte[type] = pte;
|
||
|
+#endif
|
||
|
+ set_top_pte(vaddr, pte);
|
||
|
|
||
|
return (void *)vaddr;
|
||
|
}
|
||
|
@@ -93,6 +97,9 @@ void __kunmap_atomic(void *kvaddr)
|
||
|
|
||
|
if (cache_is_vivt())
|
||
|
__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
|
||
|
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||
|
+ current->kmap_pte[type] = __pte(0);
|
||
|
+#endif
|
||
|
#ifdef CONFIG_DEBUG_HIGHMEM
|
||
|
BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
|
||
|
#else
|
||
|
@@ -110,6 +117,7 @@ EXPORT_SYMBOL(__kunmap_atomic);
|
||
|
|
||
|
void *kmap_atomic_pfn(unsigned long pfn)
|
||
|
{
|
||
|
+ pte_t pte = pfn_pte(pfn, kmap_prot);
|
||
|
unsigned long vaddr;
|
||
|
int idx, type;
|
||
|
|
||
|
@@ -121,7 +129,10 @@ void *kmap_atomic_pfn(unsigned long pfn)
|
||
|
#ifdef CONFIG_DEBUG_HIGHMEM
|
||
|
BUG_ON(!pte_none(get_top_pte(vaddr)));
|
||
|
#endif
|
||
|
- set_top_pte(vaddr, pfn_pte(pfn, kmap_prot));
|
||
|
+#ifdef CONFIG_PREEMPT_RT_FULL
|
||
|
+ current->kmap_pte[type] = pte;
|
||
|
+#endif
|
||
|
+ set_top_pte(vaddr, pte);
|
||
|
|
||
|
return (void *)vaddr;
|
||
|
}
|
||
|
@@ -135,3 +146,29 @@ struct page *kmap_atomic_to_page(const v
|
||
|
|
||
|
return pte_page(get_top_pte(vaddr));
|
||
|
}
|
||
|
+
|
||
|
+#if defined CONFIG_PREEMPT_RT_FULL
|
||
|
+void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Clear @prev's kmap_atomic mappings
|
||
|
+ */
|
||
|
+ for (i = 0; i < prev_p->kmap_idx; i++) {
|
||
|
+ int idx = i + KM_TYPE_NR * smp_processor_id();
|
||
|
+
|
||
|
+ set_top_pte(__fix_to_virt(FIX_KMAP_BEGIN + idx), __pte(0));
|
||
|
+ }
|
||
|
+ /*
|
||
|
+ * Restore @next_p's kmap_atomic mappings
|
||
|
+ */
|
||
|
+ for (i = 0; i < next_p->kmap_idx; i++) {
|
||
|
+ int idx = i + KM_TYPE_NR * smp_processor_id();
|
||
|
+
|
||
|
+ if (!pte_none(next_p->kmap_pte[i]))
|
||
|
+ set_top_pte(__fix_to_virt(FIX_KMAP_BEGIN + idx),
|
||
|
+ next_p->kmap_pte[i]);
|
||
|
+ }
|
||
|
+}
|
||
|
+#endif
|
||
|
Index: linux-stable/include/linux/highmem.h
|
||
|
===================================================================
|
||
|
--- linux-stable.orig/include/linux/highmem.h
|
||
|
+++ linux-stable/include/linux/highmem.h
|
||
|
@@ -7,6 +7,7 @@
|
||
|
#include <linux/mm.h>
|
||
|
#include <linux/uaccess.h>
|
||
|
#include <linux/hardirq.h>
|
||
|
+#include <linux/sched.h>
|
||
|
|
||
|
#include <asm/cacheflush.h>
|
||
|
|