| Subject: arm-enable-highmem-for-rt.patch |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Wed, 13 Feb 2013 11:03:11 +0100 |
| |
| 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 | 37 +++++++++++++++++++++++++++++++++++-- |
| include/linux/highmem.h | 1 + |
| 4 files changed, 46 insertions(+), 3 deletions(-) |
| |
| Index: linux-stable/arch/arm/Kconfig |
| =================================================================== |
| --- linux-stable.orig/arch/arm/Kconfig |
| +++ linux-stable/arch/arm/Kconfig |
| @@ -1749,7 +1749,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; |
| } |
| @@ -110,6 +114,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 +126,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 +143,28 @@ 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(); |
| + |
| + 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> |
| |