xref: /linux/arch/microblaze/include/asm/fixmap.h (revision 419387612c03fce2ca6d5a3d6aac3dae42069264)
1*41938761SMichal Simek /*
2*41938761SMichal Simek  * fixmap.h: compile-time virtual memory allocation
3*41938761SMichal Simek  *
4*41938761SMichal Simek  * This file is subject to the terms and conditions of the GNU General Public
5*41938761SMichal Simek  * License.  See the file "COPYING" in the main directory of this archive
6*41938761SMichal Simek  * for more details.
7*41938761SMichal Simek  *
8*41938761SMichal Simek  * Copyright (C) 1998 Ingo Molnar
9*41938761SMichal Simek  *
10*41938761SMichal Simek  * Copyright 2008 Freescale Semiconductor Inc.
11*41938761SMichal Simek  *   Port to powerpc added by Kumar Gala
12*41938761SMichal Simek  *
13*41938761SMichal Simek  * Copyright 2011 Michal Simek <monstr@monstr.eu>
14*41938761SMichal Simek  * Copyright 2011 PetaLogix Qld Pty Ltd
15*41938761SMichal Simek  *   Port to Microblaze
16*41938761SMichal Simek  */
17*41938761SMichal Simek 
18*41938761SMichal Simek #ifndef _ASM_FIXMAP_H
19*41938761SMichal Simek #define _ASM_FIXMAP_H
20*41938761SMichal Simek 
21*41938761SMichal Simek #ifndef __ASSEMBLY__
22*41938761SMichal Simek #include <linux/kernel.h>
23*41938761SMichal Simek #include <asm/page.h>
24*41938761SMichal Simek 
25*41938761SMichal Simek #define FIXADDR_TOP	((unsigned long)(-PAGE_SIZE))
26*41938761SMichal Simek 
27*41938761SMichal Simek /*
28*41938761SMichal Simek  * Here we define all the compile-time 'special' virtual
29*41938761SMichal Simek  * addresses. The point is to have a constant address at
30*41938761SMichal Simek  * compile time, but to set the physical address only
31*41938761SMichal Simek  * in the boot process. We allocate these special addresses
32*41938761SMichal Simek  * from the end of virtual memory (0xfffff000) backwards.
33*41938761SMichal Simek  * Also this lets us do fail-safe vmalloc(), we
34*41938761SMichal Simek  * can guarantee that these special addresses and
35*41938761SMichal Simek  * vmalloc()-ed addresses never overlap.
36*41938761SMichal Simek  *
37*41938761SMichal Simek  * these 'compile-time allocated' memory buffers are
38*41938761SMichal Simek  * fixed-size 4k pages. (or larger if used with an increment
39*41938761SMichal Simek  * highger than 1) use fixmap_set(idx,phys) to associate
40*41938761SMichal Simek  * physical memory with fixmap indices.
41*41938761SMichal Simek  *
42*41938761SMichal Simek  * TLB entries of such buffers will not be flushed across
43*41938761SMichal Simek  * task switches.
44*41938761SMichal Simek  */
45*41938761SMichal Simek enum fixed_addresses {
46*41938761SMichal Simek 	FIX_HOLE,
47*41938761SMichal Simek 	__end_of_fixed_addresses
48*41938761SMichal Simek };
49*41938761SMichal Simek 
50*41938761SMichal Simek extern void __set_fixmap(enum fixed_addresses idx,
51*41938761SMichal Simek 					phys_addr_t phys, pgprot_t flags);
52*41938761SMichal Simek 
53*41938761SMichal Simek #define set_fixmap(idx, phys) \
54*41938761SMichal Simek 		__set_fixmap(idx, phys, PAGE_KERNEL)
55*41938761SMichal Simek /*
56*41938761SMichal Simek  * Some hardware wants to get fixmapped without caching.
57*41938761SMichal Simek  */
58*41938761SMichal Simek #define set_fixmap_nocache(idx, phys) \
59*41938761SMichal Simek 		__set_fixmap(idx, phys, PAGE_KERNEL_CI)
60*41938761SMichal Simek 
61*41938761SMichal Simek #define clear_fixmap(idx) \
62*41938761SMichal Simek 		__set_fixmap(idx, 0, __pgprot(0))
63*41938761SMichal Simek 
64*41938761SMichal Simek #define __FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
65*41938761SMichal Simek #define FIXADDR_START		(FIXADDR_TOP - __FIXADDR_SIZE)
66*41938761SMichal Simek 
67*41938761SMichal Simek #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
68*41938761SMichal Simek #define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
69*41938761SMichal Simek 
70*41938761SMichal Simek extern void __this_fixmap_does_not_exist(void);
71*41938761SMichal Simek 
72*41938761SMichal Simek /*
73*41938761SMichal Simek  * 'index to address' translation. If anyone tries to use the idx
74*41938761SMichal Simek  * directly without tranlation, we catch the bug with a NULL-deference
75*41938761SMichal Simek  * kernel oops. Illegal ranges of incoming indices are caught too.
76*41938761SMichal Simek  */
77*41938761SMichal Simek static __always_inline unsigned long fix_to_virt(const unsigned int idx)
78*41938761SMichal Simek {
79*41938761SMichal Simek 	/*
80*41938761SMichal Simek 	 * this branch gets completely eliminated after inlining,
81*41938761SMichal Simek 	 * except when someone tries to use fixaddr indices in an
82*41938761SMichal Simek 	 * illegal way. (such as mixing up address types or using
83*41938761SMichal Simek 	 * out-of-range indices).
84*41938761SMichal Simek 	 *
85*41938761SMichal Simek 	 * If it doesn't get removed, the linker will complain
86*41938761SMichal Simek 	 * loudly with a reasonably clear error message..
87*41938761SMichal Simek 	 */
88*41938761SMichal Simek 	if (idx >= __end_of_fixed_addresses)
89*41938761SMichal Simek 		__this_fixmap_does_not_exist();
90*41938761SMichal Simek 
91*41938761SMichal Simek 	return __fix_to_virt(idx);
92*41938761SMichal Simek }
93*41938761SMichal Simek 
94*41938761SMichal Simek static inline unsigned long virt_to_fix(const unsigned long vaddr)
95*41938761SMichal Simek {
96*41938761SMichal Simek 	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
97*41938761SMichal Simek 	return __virt_to_fix(vaddr);
98*41938761SMichal Simek }
99*41938761SMichal Simek 
100*41938761SMichal Simek #endif /* !__ASSEMBLY__ */
101*41938761SMichal Simek #endif
102