xref: /linux/arch/microblaze/include/asm/fixmap.h (revision 2f2f371f8907d169650f594850ca6096e2f73b77)
141938761SMichal Simek /*
241938761SMichal Simek  * fixmap.h: compile-time virtual memory allocation
341938761SMichal Simek  *
441938761SMichal Simek  * This file is subject to the terms and conditions of the GNU General Public
541938761SMichal Simek  * License.  See the file "COPYING" in the main directory of this archive
641938761SMichal Simek  * for more details.
741938761SMichal Simek  *
841938761SMichal Simek  * Copyright (C) 1998 Ingo Molnar
941938761SMichal Simek  *
1041938761SMichal Simek  * Copyright 2008 Freescale Semiconductor Inc.
1141938761SMichal Simek  *   Port to powerpc added by Kumar Gala
1241938761SMichal Simek  *
1341938761SMichal Simek  * Copyright 2011 Michal Simek <monstr@monstr.eu>
1441938761SMichal Simek  * Copyright 2011 PetaLogix Qld Pty Ltd
1541938761SMichal Simek  *   Port to Microblaze
1641938761SMichal Simek  */
1741938761SMichal Simek 
1841938761SMichal Simek #ifndef _ASM_FIXMAP_H
1941938761SMichal Simek #define _ASM_FIXMAP_H
2041938761SMichal Simek 
2141938761SMichal Simek #ifndef __ASSEMBLY__
2241938761SMichal Simek #include <linux/kernel.h>
2341938761SMichal Simek #include <asm/page.h>
24*2f2f371fSMichal Simek #ifdef CONFIG_HIGHMEM
25*2f2f371fSMichal Simek #include <linux/threads.h>
26*2f2f371fSMichal Simek #include <asm/kmap_types.h>
27*2f2f371fSMichal Simek #endif
2841938761SMichal Simek 
2941938761SMichal Simek #define FIXADDR_TOP	((unsigned long)(-PAGE_SIZE))
3041938761SMichal Simek 
3141938761SMichal Simek /*
3241938761SMichal Simek  * Here we define all the compile-time 'special' virtual
3341938761SMichal Simek  * addresses. The point is to have a constant address at
3441938761SMichal Simek  * compile time, but to set the physical address only
3541938761SMichal Simek  * in the boot process. We allocate these special addresses
3641938761SMichal Simek  * from the end of virtual memory (0xfffff000) backwards.
3741938761SMichal Simek  * Also this lets us do fail-safe vmalloc(), we
3841938761SMichal Simek  * can guarantee that these special addresses and
3941938761SMichal Simek  * vmalloc()-ed addresses never overlap.
4041938761SMichal Simek  *
4141938761SMichal Simek  * these 'compile-time allocated' memory buffers are
4241938761SMichal Simek  * fixed-size 4k pages. (or larger if used with an increment
4341938761SMichal Simek  * highger than 1) use fixmap_set(idx,phys) to associate
4441938761SMichal Simek  * physical memory with fixmap indices.
4541938761SMichal Simek  *
4641938761SMichal Simek  * TLB entries of such buffers will not be flushed across
4741938761SMichal Simek  * task switches.
4841938761SMichal Simek  */
4941938761SMichal Simek enum fixed_addresses {
5041938761SMichal Simek 	FIX_HOLE,
51*2f2f371fSMichal Simek #ifdef CONFIG_HIGHMEM
52*2f2f371fSMichal Simek 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
53*2f2f371fSMichal Simek 	FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * num_possible_cpus()) - 1,
54*2f2f371fSMichal Simek #endif
5541938761SMichal Simek 	__end_of_fixed_addresses
5641938761SMichal Simek };
5741938761SMichal Simek 
5841938761SMichal Simek extern void __set_fixmap(enum fixed_addresses idx,
5941938761SMichal Simek 					phys_addr_t phys, pgprot_t flags);
6041938761SMichal Simek 
6141938761SMichal Simek #define set_fixmap(idx, phys) \
6241938761SMichal Simek 		__set_fixmap(idx, phys, PAGE_KERNEL)
6341938761SMichal Simek /*
6441938761SMichal Simek  * Some hardware wants to get fixmapped without caching.
6541938761SMichal Simek  */
6641938761SMichal Simek #define set_fixmap_nocache(idx, phys) \
6741938761SMichal Simek 		__set_fixmap(idx, phys, PAGE_KERNEL_CI)
6841938761SMichal Simek 
6941938761SMichal Simek #define clear_fixmap(idx) \
7041938761SMichal Simek 		__set_fixmap(idx, 0, __pgprot(0))
7141938761SMichal Simek 
7241938761SMichal Simek #define __FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
7341938761SMichal Simek #define FIXADDR_START		(FIXADDR_TOP - __FIXADDR_SIZE)
7441938761SMichal Simek 
7541938761SMichal Simek #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
7641938761SMichal Simek #define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
7741938761SMichal Simek 
7841938761SMichal Simek extern void __this_fixmap_does_not_exist(void);
7941938761SMichal Simek 
8041938761SMichal Simek /*
8141938761SMichal Simek  * 'index to address' translation. If anyone tries to use the idx
8241938761SMichal Simek  * directly without tranlation, we catch the bug with a NULL-deference
8341938761SMichal Simek  * kernel oops. Illegal ranges of incoming indices are caught too.
8441938761SMichal Simek  */
8541938761SMichal Simek static __always_inline unsigned long fix_to_virt(const unsigned int idx)
8641938761SMichal Simek {
8741938761SMichal Simek 	/*
8841938761SMichal Simek 	 * this branch gets completely eliminated after inlining,
8941938761SMichal Simek 	 * except when someone tries to use fixaddr indices in an
9041938761SMichal Simek 	 * illegal way. (such as mixing up address types or using
9141938761SMichal Simek 	 * out-of-range indices).
9241938761SMichal Simek 	 *
9341938761SMichal Simek 	 * If it doesn't get removed, the linker will complain
9441938761SMichal Simek 	 * loudly with a reasonably clear error message..
9541938761SMichal Simek 	 */
9641938761SMichal Simek 	if (idx >= __end_of_fixed_addresses)
9741938761SMichal Simek 		__this_fixmap_does_not_exist();
9841938761SMichal Simek 
9941938761SMichal Simek 	return __fix_to_virt(idx);
10041938761SMichal Simek }
10141938761SMichal Simek 
10241938761SMichal Simek static inline unsigned long virt_to_fix(const unsigned long vaddr)
10341938761SMichal Simek {
10441938761SMichal Simek 	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
10541938761SMichal Simek 	return __virt_to_fix(vaddr);
10641938761SMichal Simek }
10741938761SMichal Simek 
10841938761SMichal Simek #endif /* !__ASSEMBLY__ */
10941938761SMichal Simek #endif
110