From: James Hogan <james.hogan@imgtec.com>
To: <linux-kernel@vger.kernel.org>, <linux-arch@vger.kernel.org>
Cc: James Hogan <james.hogan@imgtec.com>
Subject: [PATCH v3 16/44] metag: Highmem support
Date: Thu, 10 Jan 2013 15:30:44 +0000 [thread overview]
Message-ID: <1357831872-29451-17-git-send-email-james.hogan@imgtec.com> (raw)
In-Reply-To: <1357831872-29451-1-git-send-email-james.hogan@imgtec.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
---
arch/metag/include/asm/fixmap.h | 99 ++++++++++++++++++++++++++++
arch/metag/include/asm/highmem.h | 62 ++++++++++++++++++
arch/metag/mm/highmem.c | 133 ++++++++++++++++++++++++++++++++++++++
3 files changed, 294 insertions(+), 0 deletions(-)
create mode 100644 arch/metag/include/asm/fixmap.h
create mode 100644 arch/metag/include/asm/highmem.h
create mode 100644 arch/metag/mm/highmem.c
diff --git a/arch/metag/include/asm/fixmap.h b/arch/metag/include/asm/fixmap.h
new file mode 100644
index 0000000..3331275
--- /dev/null
+++ b/arch/metag/include/asm/fixmap.h
@@ -0,0 +1,99 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Ingo Molnar
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+#include <asm/pgtable.h>
+#ifdef CONFIG_HIGHMEM
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#endif
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process. We allocate these special addresses
+ * from the end of the consistent memory region backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * these 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages. (or larger if used with an increment
+ * higher than 1) use fixmap_set(idx,phys) to associate
+ * physical memory with fixmap indices.
+ *
+ * TLB entries of such buffers will not be flushed across
+ * task switches.
+ */
+enum fixed_addresses {
+#define FIX_N_COLOURS 8
+#ifdef CONFIG_HIGHMEM
+ /* reserved pte's for temporary kernel mappings */
+ FIX_KMAP_BEGIN,
+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+#endif
+ __end_of_fixed_addresses
+};
+
+#define FIXADDR_TOP (CONSISTENT_START - PAGE_SIZE)
+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK)
+
+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without tranlation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static inline unsigned long fix_to_virt(const unsigned int idx)
+{
+ /*
+ * this branch gets completely eliminated after inlining,
+ * except when someone tries to use fixaddr indices in an
+ * illegal way. (such as mixing up address types or using
+ * out-of-range indices).
+ *
+ * If it doesn't get removed, the linker will complain
+ * loudly with a reasonably clear error message..
+ */
+ if (idx >= __end_of_fixed_addresses)
+ __this_fixmap_does_not_exist();
+
+ return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+ BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+ return __virt_to_fix(vaddr);
+}
+
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel( \
+ pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), \
+ (vaddr) \
+ )
+
+/*
+ * Called from pgtable_init()
+ */
+extern void fixrange_init(unsigned long start, unsigned long end,
+ pgd_t *pgd_base);
+
+
+#endif
diff --git a/arch/metag/include/asm/highmem.h b/arch/metag/include/asm/highmem.h
new file mode 100644
index 0000000..6646a15
--- /dev/null
+++ b/arch/metag/include/asm/highmem.h
@@ -0,0 +1,62 @@
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#include <asm/cacheflush.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+/*
+ * Ordering is (from lower to higher memory addresses):
+ *
+ * high_memory
+ * Persistent kmap area
+ * PKMAP_BASE
+ * fixed_addresses
+ * FIXADDR_START
+ * FIXADDR_TOP
+ * Vmalloc area
+ * VMALLOC_START
+ * VMALLOC_END
+ */
+#define PKMAP_BASE (FIXADDR_START - PMD_SIZE)
+#define LAST_PKMAP PTRS_PER_PTE
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define kmap_prot PAGE_KERNEL
+
+static inline void flush_cache_kmaps(void)
+{
+ flush_cache_all();
+}
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+extern pte_t *pkmap_page_table;
+
+extern void *kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+extern void kmap_init(void);
+
+/*
+ * The following functions are already defined by <linux/highmem.h>
+ * when CONFIG_HIGHMEM is not set.
+ */
+#ifdef CONFIG_HIGHMEM
+extern void *kmap(struct page *page);
+extern void kunmap(struct page *page);
+extern void *kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
+extern void *kmap_atomic_pfn(unsigned long pfn);
+extern struct page *kmap_atomic_to_page(void *ptr);
+#endif
+
+#endif
diff --git a/arch/metag/mm/highmem.c b/arch/metag/mm/highmem.c
new file mode 100644
index 0000000..d71f621
--- /dev/null
+++ b/arch/metag/mm/highmem.c
@@ -0,0 +1,133 @@
+#include <linux/export.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <asm/fixmap.h>
+#include <asm/tlbflush.h>
+
+static pte_t *kmap_pte;
+
+unsigned long highstart_pfn, highend_pfn;
+
+void *kmap(struct page *page)
+{
+ might_sleep();
+ if (!PageHighMem(page))
+ return page_address(page);
+ return kmap_high(page);
+}
+EXPORT_SYMBOL(kmap);
+
+void kunmap(struct page *page)
+{
+ BUG_ON(in_interrupt());
+ if (!PageHighMem(page))
+ return;
+ kunmap_high(page);
+}
+EXPORT_SYMBOL(kunmap);
+
+/*
+ * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
+ * no global lock is needed and because the kmap code must perform a global TLB
+ * invalidation when the kmap pool wraps.
+ *
+ * However when holding an atomic kmap is is not legal to sleep, so atomic
+ * kmaps are appropriate for short, tight code paths only.
+ */
+
+void *kmap_atomic(struct page *page)
+{
+ enum fixed_addresses idx;
+ unsigned long vaddr;
+ int type;
+
+ /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+ pagefault_disable();
+ if (!PageHighMem(page))
+ return page_address(page);
+
+ type = kmap_atomic_idx_push();
+ idx = type + KM_TYPE_NR * smp_processor_id();
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+ BUG_ON(!pte_none(*(kmap_pte - idx)));
+#endif
+ set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL));
+
+ return (void *)vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic);
+
+void __kunmap_atomic(void *kvaddr)
+{
+ unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+ int idx, type;
+
+ if (kvaddr >= (void *)FIXADDR_START) {
+ type = kmap_atomic_idx();
+ idx = type + KM_TYPE_NR * smp_processor_id();
+
+ /*
+ * Force other mappings to Oops if they'll try to access this
+ * pte without first remap it. Keeping stale mappings around
+ * is a bad idea also, in case the page changes cacheability
+ * attributes or becomes a protected page in a hypervisor.
+ */
+ pte_clear(&init_mm, vaddr, kmap_pte-idx);
+ flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
+
+ kmap_atomic_idx_pop();
+ }
+
+ pagefault_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
+
+/*
+ * This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn)
+{
+ enum fixed_addresses idx;
+ unsigned long vaddr;
+ int type;
+
+ pagefault_disable();
+
+ type = kmap_atomic_idx_push();
+ idx = type + KM_TYPE_NR * smp_processor_id();
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+ BUG_ON(!pte_none(*(kmap_pte - idx)));
+#endif
+ set_pte(kmap_pte - idx, pfn_pte(pfn, PAGE_KERNEL));
+ flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
+
+ return (void *)vaddr;
+}
+
+struct page *kmap_atomic_to_page(void *ptr)
+{
+ unsigned long vaddr = (unsigned long)ptr;
+ int idx;
+ pte_t *pte;
+
+ if (vaddr < FIXADDR_START)
+ return virt_to_page(ptr);
+
+ idx = virt_to_fix(vaddr);
+ pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
+ return pte_page(*pte);
+}
+
+void __init kmap_init(void)
+{
+ unsigned long kmap_vstart;
+
+ /* cache the first kmap pte */
+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+}
--
1.7.7.6
next prev parent reply other threads:[~2013-01-10 15:41 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-10 15:30 [PATCH v3 00/44] Meta Linux Kernel Port James Hogan
2013-01-10 15:30 ` [PATCH v3 01/44] asm-generic/io.h: check CONFIG_VIRT_TO_BUS James Hogan
2013-01-10 15:30 ` [PATCH v3 02/44] asm-generic/unistd.h: handle symbol prefixes in cond_syscall James Hogan
2013-01-10 15:30 ` [PATCH v3 03/44] Revert some of "binfmt_elf: cleanups" James Hogan
2013-01-10 15:30 ` [PATCH v3 04/44] Add HAVE_64BIT_ALIGNED_ACCESS James Hogan
2013-01-10 15:30 ` [PATCH v3 05/44] trace/ring_buffer: handle 64bit aligned structs James Hogan
2013-01-10 15:30 ` [PATCH v3 06/44] metag: Add MAINTAINERS entry James Hogan
2013-01-10 15:30 ` [PATCH v3 07/44] metag: Headers for core arch constants James Hogan
2013-01-10 15:30 ` [PATCH v3 08/44] metag: Header for core memory mapped registers James Hogan
2013-01-10 15:30 ` [PATCH v3 09/44] metag: Boot James Hogan
2013-01-10 15:30 ` [PATCH v3 10/44] metag: TBX header James Hogan
2013-01-10 15:30 ` [PATCH v3 11/44] metag: TBX source James Hogan
2013-01-10 15:30 ` [PATCH v3 12/44] metag: Cache/TLB handling James Hogan
2013-01-10 15:30 ` [PATCH v3 13/44] metag: Memory management James Hogan
2013-01-10 15:30 ` [PATCH v3 14/44] metag: Memory handling James Hogan
2013-01-10 15:30 ` [PATCH v3 15/44] metag: Huge TLB James Hogan
2013-01-10 16:57 ` Dave Hansen
2013-01-11 9:58 ` James Hogan
2013-01-10 15:30 ` James Hogan [this message]
2013-01-10 15:30 ` [PATCH v3 17/44] metag: TCM support James Hogan
2013-01-10 15:30 ` [PATCH v3 18/44] metag: Signal handling James Hogan
2013-01-10 15:30 ` [PATCH v3 19/44] metag: Device tree James Hogan
2013-02-06 13:06 ` Vineet Gupta
2013-02-06 13:47 ` James Hogan
2013-01-10 15:30 ` [PATCH v3 20/44] metag: ptrace James Hogan
2013-01-10 15:30 ` [PATCH v3 21/44] metag: Time keeping James Hogan
2013-01-26 0:03 ` Arnd Bergmann
2013-01-28 12:59 ` James Hogan
2013-01-10 15:30 ` [PATCH v3 22/44] metag: Traps James Hogan
2013-01-10 15:30 ` [PATCH v3 23/44] metag: IRQ handling James Hogan
2013-01-10 15:30 ` [PATCH v3 24/44] metag: Internal and external irqchips James Hogan
2013-01-10 15:30 ` [PATCH v3 25/44] metag: System Calls James Hogan
2013-01-10 15:30 ` [PATCH v3 26/44] metag: Scheduling/Process management James Hogan
2013-01-10 15:30 ` [PATCH v3 27/44] metag: Module support James Hogan
2013-01-10 15:30 ` [PATCH v3 28/44] metag: Atomics, locks and bitops James Hogan
2013-01-10 15:30 ` [PATCH v3 29/44] metag: Basic documentation James Hogan
2013-01-10 15:30 ` [PATCH v3 30/44] metag: SMP support James Hogan
2013-01-10 15:30 ` [PATCH v3 31/44] metag: DMA James Hogan
2013-01-10 15:31 ` [PATCH v3 32/44] metag: Optimised library functions James Hogan
2013-01-10 15:31 ` [PATCH v3 33/44] metag: Stack unwinding James Hogan
2013-01-10 15:31 ` [PATCH v3 34/44] metag: Various other headers James Hogan
2013-01-10 15:31 ` [PATCH v3 35/44] mm: define VM_GROWSUP for CONFIG_METAG James Hogan
2013-01-10 15:31 ` [PATCH v3 36/44] Kconfig.debug: add METAG to dependency lists James Hogan
2013-01-10 15:31 ` [PATCH v3 37/44] metag: Build infrastructure James Hogan
2013-01-10 15:31 ` [PATCH v3 38/44] metag: Perf James Hogan
2013-01-10 15:31 ` [PATCH v3 39/44] metag: ftrace support James Hogan
2013-01-10 15:59 ` Steven Rostedt
2013-01-10 16:00 ` Steven Rostedt
2013-01-10 16:13 ` James Hogan
2013-01-10 15:31 ` [PATCH v3 40/44] scripts/checkstack.pl: Add metag support James Hogan
2013-01-10 15:31 ` [PATCH v3 41/44] metag: OProfile James Hogan
2013-01-10 17:12 ` Maynard Johnson
2013-01-11 9:43 ` James Hogan
2013-01-10 15:31 ` [PATCH v3 42/44] metag: Add JTAG Debug Adapter (DA) support James Hogan
2013-01-10 15:31 ` [PATCH v3 43/44] tty/metag_da: Add metag DA TTY driver James Hogan
2013-01-10 16:03 ` Jiri Slaby
2013-01-11 10:50 ` James Hogan
2013-01-14 10:15 ` Jiri Slaby
2013-01-14 10:54 ` James Hogan
2013-01-25 11:36 ` James Hogan
2013-01-30 5:14 ` Greg Kroah-Hartman
2013-01-30 10:43 ` James Hogan
2013-01-10 15:31 ` [PATCH v3 44/44] fs: imgdafs: Add IMG DAFS filesystem for metag James Hogan
2013-01-28 13:28 ` James Hogan
2013-01-10 23:34 ` [PATCH v3 00/44] Meta Linux Kernel Port Stephen Rothwell
2013-01-11 9:15 ` James Hogan
2013-01-11 13:03 ` Stephen Rothwell
2013-01-11 13:16 ` James Hogan
2013-01-11 15:02 ` James Hogan
2013-01-12 1:09 ` Stephen Rothwell
2013-01-12 9:55 ` James Hogan
2013-01-12 14:56 ` Stephen Rothwell
2013-01-19 5:55 ` Al Viro
2013-01-22 11:35 ` James Hogan
2013-01-25 17:04 ` James Hogan
2013-01-26 0:25 ` Arnd Bergmann
2013-01-26 21:53 ` James Hogan
2013-01-28 7:10 ` Vineet Gupta
2013-01-28 11:08 ` James Hogan
2013-01-29 12:45 ` ARC Port for linux-next (was Re: [PATCH v3 00/44] Meta Linux Kernel Port) Vineet Gupta
2013-01-29 20:44 ` [PATCH v3 00/44] Meta Linux Kernel Port Stephen Rothwell
2013-01-29 20:50 ` Stephen Rothwell
2013-02-01 8:18 ` linux-net for ARC port Vineet Gupta
2013-02-01 12:05 ` Stephen Rothwell
2013-02-01 12:33 ` Geert Uytterhoeven
2013-02-01 12:59 ` Stephen Rothwell
2013-02-05 13:54 ` [PATCH v3 00/44] Meta Linux Kernel Port Vineet Gupta
2013-02-05 23:40 ` rkuo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1357831872-29451-17-git-send-email-james.hogan@imgtec.com \
--to=james.hogan@imgtec.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®