xref: /linux/arch/m68k/include/asm/page_mm.h (revision fc9c7ca5fcbf7fe3bcba87d1ff72f0009071ba86)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _M68K_PAGE_MM_H
3 #define _M68K_PAGE_MM_H
4 
5 #ifndef __ASSEMBLER__
6 
7 #include <linux/compiler.h>
8 #include <asm/module.h>
9 
10 /*
11  * We don't need to check for alignment etc.
12  */
13 #ifdef CPU_M68040_OR_M68060_ONLY
14 static inline void copy_page(void *to, void *from)
15 {
16 	unsigned long tmp;
17 
18 	__asm__ __volatile__("1:\t"
19 			     ".chip 68040\n\t"
20 			     "move16 %1@+,%0@+\n\t"
21 			     "move16 %1@+,%0@+\n\t"
22 			     ".chip 68k\n\t"
23 			     "dbra  %2,1b\n\t"
24 			     : "=a" (to), "=a" (from), "=d" (tmp)
25 			     : "0" (to), "1" (from), "2" (PAGE_SIZE / 32 - 1));
26 }
27 
28 static inline void clear_page(void *page)
29 {
30 	unsigned long tmp;
31 	unsigned long *sp = page;
32 
33 	*sp++ = 0;
34 	*sp++ = 0;
35 	*sp++ = 0;
36 	*sp++ = 0;
37 
38 	__asm__ __volatile__("1:\t"
39 			     ".chip 68040\n\t"
40 			     "move16 %2@+,%0@+\n\t"
41 			     ".chip 68k\n\t"
42 			     "subqw  #8,%2\n\t"
43 			     "subqw  #8,%2\n\t"
44 			     "dbra   %1,1b\n\t"
45 			     : "=a" (sp), "=d" (tmp)
46 			     : "a" (page), "0" (sp),
47 			       "1" ((PAGE_SIZE - 16) / 16 - 1));
48 }
49 
50 #else
51 #define clear_page(page)	memset((page), 0, PAGE_SIZE)
52 #define copy_page(to,from)	memcpy((to), (from), PAGE_SIZE)
53 #endif
54 
55 #define clear_user_page(addr, vaddr, page)	\
56 	do {	clear_page(addr);		\
57 		flush_dcache_page(page);	\
58 		(void)(vaddr);			\
59 	} while (0)
60 #define copy_user_page(to, from, vaddr, page)	\
61 	do {	copy_page(to, from);		\
62 		flush_dcache_page(page);	\
63 		(void)(vaddr);			\
64 	} while (0)
65 
66 extern unsigned long m68k_memoffset;
67 
68 #ifndef CONFIG_SUN3
69 
70 #define WANT_PAGE_VIRTUAL
71 
72 static inline unsigned long ___pa(void *vaddr)
73 {
74 	unsigned long paddr;
75 	asm (
76 		"1:	addl #0,%0\n"
77 		m68k_fixup(%c2, 1b+2)
78 		: "=r" (paddr)
79 		: "0" (vaddr), "i" (m68k_fixup_memoffset));
80 	return paddr;
81 }
82 #define __pa(vaddr)	___pa((void *)(long)(vaddr))
83 static inline void *__va(unsigned long paddr)
84 {
85 	void *vaddr;
86 	asm (
87 		"1:	subl #0,%0\n"
88 		m68k_fixup(%c2, 1b+2)
89 		: "=r" (vaddr)
90 		: "0" (paddr), "i" (m68k_fixup_memoffset));
91 	return vaddr;
92 }
93 
94 #else	/* !CONFIG_SUN3 */
95 /* This #define is a horrible hack to suppress lots of warnings. --m */
96 #define __pa(x) ___pa((unsigned long)(x))
97 static inline unsigned long ___pa(unsigned long x)
98 {
99 	if (x == 0)
100 		return 0;
101 	if (x >= PAGE_OFFSET)
102 		return (x - PAGE_OFFSET);
103 	else
104 		return (x + 0x2000000);
105 }
106 
107 static inline void *__va(unsigned long x)
108 {
109 	if (x == 0)
110 		return (void *)0;
111 
112 	if (x < 0x2000000)
113 		return (void *)(x + PAGE_OFFSET);
114 	else
115 		return (void *)(x - 0x2000000);
116 }
117 #endif	/* CONFIG_SUN3 */
118 
119 /*
120  * NOTE: virtual isn't really correct, actually it should be the offset into the
121  * memory node, but we have no highmem, so that works for now.
122  * TODO: implement (fast) pfn<->pgdat_idx conversion functions, this makes lots
123  * of the shifts unnecessary.
124  */
125 static inline unsigned long virt_to_pfn(const void *kaddr)
126 {
127 	return __pa(kaddr) >> PAGE_SHIFT;
128 }
129 
130 static inline void *pfn_to_virt(unsigned long pfn)
131 {
132 	return __va(pfn << PAGE_SHIFT);
133 }
134 
135 extern int m68k_virt_to_node_shift;
136 
137 #define virt_to_page(addr) ({						\
138 	pfn_to_page(virt_to_pfn(addr));					\
139 })
140 #define page_to_virt(page) ({						\
141 	pfn_to_virt(page_to_pfn(page));					\
142 })
143 
144 #define ARCH_PFN_OFFSET (m68k_memory[0].addr >> PAGE_SHIFT)
145 
146 #define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
147 #define pfn_valid(pfn)		virt_addr_valid(pfn_to_virt(pfn))
148 
149 #endif /* __ASSEMBLER__ */
150 
151 #endif /* _M68K_PAGE_MM_H */
152