microblaze: Introduce fixmap
authorMichal Simek <monstr@monstr.eu>
Thu, 15 Dec 2011 13:33:32 +0000 (14:33 +0100)
committerMichal Simek <monstr@monstr.eu>
Fri, 23 Mar 2012 08:28:11 +0000 (09:28 +0100)
Fixmap will be used for highmem support.

Signed-off-by: Michal Simek <monstr@monstr.eu>
arch/microblaze/include/asm/fixmap.h [new file with mode: 0644]
arch/microblaze/mm/init.c
arch/microblaze/mm/pgtable.c

diff --git a/arch/microblaze/include/asm/fixmap.h b/arch/microblaze/include/asm/fixmap.h
new file mode 100644 (file)
index 0000000..dd89754
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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
+ *
+ * Copyright 2008 Freescale Semiconductor Inc.
+ *   Port to powerpc added by Kumar Gala
+ *
+ * Copyright 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright 2011 PetaLogix Qld Pty Ltd
+ *   Port to Microblaze
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+#ifndef __ASSEMBLY__
+#include <linux/kernel.h>
+#include <asm/page.h>
+
+#define FIXADDR_TOP    ((unsigned long)(-PAGE_SIZE))
+
+/*
+ * 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 virtual memory (0xfffff000) 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
+ * highger 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 {
+       FIX_HOLE,
+       __end_of_fixed_addresses
+};
+
+extern void __set_fixmap(enum fixed_addresses idx,
+                                       phys_addr_t phys, pgprot_t flags);
+
+#define set_fixmap(idx, phys) \
+               __set_fixmap(idx, phys, PAGE_KERNEL)
+/*
+ * Some hardware wants to get fixmapped without caching.
+ */
+#define set_fixmap_nocache(idx, phys) \
+               __set_fixmap(idx, phys, PAGE_KERNEL_CI)
+
+#define clear_fixmap(idx) \
+               __set_fixmap(idx, 0, __pgprot(0))
+
+#define __FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START          (FIXADDR_TOP - __FIXADDR_SIZE)
+
+#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 __always_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);
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif
index 2253e122aa85e54c4c1ab593f5f622efe450f8e4..af87fd71a83e26c3f7bc97c0c6672d68ec0ed93b 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
 #include <asm/tlb.h>
+#include <asm/fixmap.h>
 
 /* Use for MMU and noMMU because of PCI generic code */
 int mem_init_done;
@@ -54,6 +55,13 @@ unsigned long lowmem_size;
 static void __init paging_init(void)
 {
        unsigned long zones_size[MAX_NR_ZONES];
+#ifdef CONFIG_MMU
+       int idx;
+
+       /* Setup fixmaps */
+       for (idx = 0; idx < __end_of_fixed_addresses; idx++)
+               clear_fixmap(idx);
+#endif
 
        /* Clean every zones */
        memset(zones_size, 0, sizeof(zones_size));
@@ -316,12 +324,9 @@ asmlinkage void __init mmu_init(void)
        /* Map in all of RAM starting at CONFIG_KERNEL_START */
        mapin_ram();
 
-#ifdef CONFIG_HIGHMEM_START_BOOL
-       ioremap_base = CONFIG_HIGHMEM_START;
-#else
-       ioremap_base = 0xfe000000UL;    /* for now, could be 0xfffff000 */
-#endif /* CONFIG_HIGHMEM_START_BOOL */
-       ioremap_bot = ioremap_base;
+       /* Extend vmalloc and ioremap area as big as possible */
+       ioremap_base = ioremap_bot = FIXADDR_START;
+
        /* Initialize the context management stuff */
        mmu_context_init();
 
index 68f5c01e4ad10477749422f50d7c548369b410a7..84905da83cb7c0639dfec0b033a8bd99b0541c09 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/io.h>
 #include <asm/mmu.h>
 #include <asm/sections.h>
+#include <asm/fixmap.h>
 
 #define flush_HPTE(X, va, pg)  _tlbie(va)
 
@@ -249,3 +250,13 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
        }
        return pte;
 }
+
+void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
+{
+       unsigned long address = __fix_to_virt(idx);
+
+       if (idx >= __end_of_fixed_addresses)
+               BUG();
+
+       map_page(address, phys, pgprot_val(flags));
+}