page.h 7.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * 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) 1994 - 1999, 2000, 03 Ralf Baechle
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
 */
#ifndef _ASM_PAGE_H
#define _ASM_PAGE_H

#include <spaces.h>
13
#include <linux/const.h>
L
Leonid Yegoshin 已提交
14 15
#include <linux/kernel.h>
#include <asm/mipsregs.h>
L
Linus Torvalds 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28

/*
 * PAGE_SHIFT determines the page size
 */
#ifdef CONFIG_PAGE_SIZE_4KB
#define PAGE_SHIFT	12
#endif
#ifdef CONFIG_PAGE_SIZE_8KB
#define PAGE_SHIFT	13
#endif
#ifdef CONFIG_PAGE_SIZE_16KB
#define PAGE_SHIFT	14
#endif
29 30 31
#ifdef CONFIG_PAGE_SIZE_32KB
#define PAGE_SHIFT	15
#endif
L
Linus Torvalds 已提交
32 33 34
#ifdef CONFIG_PAGE_SIZE_64KB
#define PAGE_SHIFT	16
#endif
35
#define PAGE_SIZE	(_AC(1,UL) << PAGE_SHIFT)
36
#define PAGE_MASK	(~((1 << PAGE_SHIFT) - 1))
L
Linus Torvalds 已提交
37

L
Leonid Yegoshin 已提交
38 39
/*
 * This is used for calculating the real page sizes
40
 * for FTLB or VTLB + FTLB configurations.
L
Leonid Yegoshin 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
 */
static inline unsigned int page_size_ftlb(unsigned int mmuextdef)
{
	switch (mmuextdef) {
	case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT:
		if (PAGE_SIZE == (1 << 30))
			return 5;
		if (PAGE_SIZE == (1llu << 32))
			return 6;
		if (PAGE_SIZE > (256 << 10))
			return 7; /* reserved */
			/* fall through */
	case MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT:
		return (PAGE_SHIFT - 10) / 2;
	default:
		panic("Invalid FTLB configuration with Conf4_mmuextdef=%d value\n",
		      mmuextdef >> 14);
	}
}

61
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
D
David Daney 已提交
62
#define HPAGE_SHIFT	(PAGE_SHIFT + PAGE_SHIFT - 3)
63
#define HPAGE_SIZE	(_AC(1,UL) << HPAGE_SHIFT)
D
David Daney 已提交
64 65
#define HPAGE_MASK	(~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
66
#else /* !CONFIG_MIPS_HUGE_TLB_SUPPORT */
H
Hillf Danton 已提交
67 68 69 70
#define HPAGE_SHIFT	({BUILD_BUG(); 0; })
#define HPAGE_SIZE	({BUILD_BUG(); 0; })
#define HPAGE_MASK	({BUILD_BUG(); 0; })
#define HUGETLB_PAGE_ORDER	({BUILD_BUG(); 0; })
71
#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
D
David Daney 已提交
72

73
#include <linux/pfn.h>
74

75 76 77
extern void build_clear_page(void);
extern void build_copy_page(void);

78 79 80 81 82 83 84
/*
 * It's normally defined only for FLATMEM config but it's
 * used in our early mem init code for all memory models.
 * So always define it.
 */
#define ARCH_PFN_OFFSET		PFN_UP(PHYS_OFFSET)

L
Linus Torvalds 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
extern void clear_page(void * page);
extern void copy_page(void * to, void * from);

extern unsigned long shm_align_mask;

static inline unsigned long pages_do_alias(unsigned long addr1,
	unsigned long addr2)
{
	return (addr1 ^ addr2) & shm_align_mask;
}

struct page;

static inline void clear_user_page(void *addr, unsigned long vaddr,
	struct page *page)
{
	extern void (*flush_data_cache_page)(unsigned long addr);

	clear_page(addr);
104
	if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK))
L
Linus Torvalds 已提交
105 106 107
		flush_data_cache_page((unsigned long)addr);
}

108 109 110
struct vm_area_struct;
extern void copy_user_highpage(struct page *to, struct page *from,
	unsigned long vaddr, struct vm_area_struct *vma);
L
Linus Torvalds 已提交
111

112
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
L
Linus Torvalds 已提交
113 114 115 116

/*
 * These are used to make use of C type-checking..
 */
117
#ifdef CONFIG_PHYS_ADDR_T_64BIT
118
  #ifdef CONFIG_CPU_MIPS32
L
Linus Torvalds 已提交
119
    typedef struct { unsigned long pte_low, pte_high; } pte_t;
R
Ralf Baechle 已提交
120 121
    #define pte_val(x)	  ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
    #define __pte(x)	  ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; })
L
Linus Torvalds 已提交
122 123
  #else
     typedef struct { unsigned long long pte; } pte_t;
R
Ralf Baechle 已提交
124
     #define pte_val(x) ((x).pte)
125
     #define __pte(x)	((pte_t) { (x) } )
L
Linus Torvalds 已提交
126 127 128 129
  #endif
#else
typedef struct { unsigned long pte; } pte_t;
#define pte_val(x)	((x).pte)
130
#define __pte(x)	((pte_t) { (x) } )
131
#endif
132
typedef struct page *pgtable_t;
L
Linus Torvalds 已提交
133

134 135 136 137 138 139 140 141 142 143
/*
 * Right now we don't support 4-level pagetables, so all pud-related
 * definitions come from <asm-generic/pgtable-nopud.h>.
 */

/*
 * Finall the top of the hierarchy, the pgd
 */
typedef struct { unsigned long pgd; } pgd_t;
#define pgd_val(x)	((x).pgd)
L
Linus Torvalds 已提交
144
#define __pgd(x)	((pgd_t) { (x) } )
145 146 147 148 149 150

/*
 * Manipulate page protection bits
 */
typedef struct { unsigned long pgprot; } pgprot_t;
#define pgprot_val(x)	((x).pgprot)
L
Linus Torvalds 已提交
151 152
#define __pgprot(x)	((pgprot_t) { (x) } )

153 154 155 156 157 158 159 160 161
/*
 * On R4000-style MMUs where a TLB entry is mapping a adjacent even / odd
 * pair of pages we only have a single global bit per pair of pages.  When
 * writing to the TLB make sure we always have the bit set for both pages
 * or none.  This macro is used to access the `buddy' of the pte we're just
 * working on.
 */
#define ptep_buddy(x)	((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))

162 163 164
/*
 * __pa()/__va() should be used only during mem init.
 */
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
static inline unsigned long ___pa(unsigned long x)
{
	if (config_enabled(CONFIG_64BIT)) {
		/*
		 * For MIPS64 the virtual address may either be in one of
		 * the compatibility segements ckseg0 or ckseg1, or it may
		 * be in xkphys.
		 */
		return x < CKSEG0 ? XPHYSADDR(x) : CPHYSADDR(x);
	}

	if (!config_enabled(CONFIG_EVA)) {
		/*
		 * We're using the standard MIPS32 legacy memory map, ie.
		 * the address x is going to be in kseg0 or kseg1. We can
		 * handle either case by masking out the desired bits using
		 * CPHYSADDR.
		 */
		return CPHYSADDR(x);
	}

	/*
	 * EVA is in use so the memory map could be anything, making it not
	 * safe to just mask out bits.
	 */
	return x - PAGE_OFFSET + PHYS_OFFSET;
}
#define __pa(x)		___pa((unsigned long)(x))
193
#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
194
#include <asm/io.h>
195 196 197 198 199 200 201 202 203 204 205 206 207 208

/*
 * RELOC_HIDE was originally added by 6007b903dfe5f1d13e0c711ac2894bdd4a61b1ad
 * (lmo) rsp. 8431fd094d625b94d364fe393076ccef88e6ce18 (kernel.org).  The
 * discussion can be found in lkml posting
 * <a2ebde260608230500o3407b108hc03debb9da6e62c@mail.gmail.com> which is
 * archived at http://lists.linuxcoding.com/kernel/2006-q3/msg17360.html
 *
 * It is unclear if the misscompilations mentioned in
 * http://lkml.org/lkml/2010/8/8/138 also affect MIPS so we keep this one
 * until GCC 3.x has been retired before we can apply
 * https://patchwork.linux-mips.org/patch/1541/
 */

209
#ifndef __pa_symbol
210
#define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x), 0))
211
#endif
L
Linus Torvalds 已提交
212 213 214

#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)

215 216
#ifdef CONFIG_FLATMEM

217 218 219 220
static inline int pfn_valid(unsigned long pfn)
{
	/* avoid <linux/mm.h> include hell */
	extern unsigned long max_mapnr;
221
	unsigned long pfn_offset = ARCH_PFN_OFFSET;
222

223
	return pfn >= pfn_offset && pfn < max_mapnr;
224
}
225

A
Atsushi Nemoto 已提交
226 227 228 229
#elif defined(CONFIG_SPARSEMEM)

/* pfn_valid is defined in linux/mmzone.h */

230 231 232 233 234 235 236
#elif defined(CONFIG_NEED_MULTIPLE_NODES)

#define pfn_valid(pfn)							\
({									\
	unsigned long __pfn = (pfn);					\
	int __n = pfn_to_nid(__pfn);					\
	((__n >= 0) ? (__pfn < NODE_DATA(__n)->node_start_pfn +		\
R
Ralf Baechle 已提交
237 238
			       NODE_DATA(__n)->node_spanned_pages)	\
		    : 0);						\
239 240 241 242
})

#endif

243 244
#define virt_to_page(kaddr)	pfn_to_page(PFN_DOWN(virt_to_phys((void *)     \
								  (kaddr))))
245 246 247 248

extern int __virt_addr_valid(const volatile void *kaddr);
#define virt_addr_valid(kaddr)						\
	__virt_addr_valid((const volatile void *) (kaddr))
L
Linus Torvalds 已提交
249

250 251 252 253
#define VM_DATA_DEFAULT_FLAGS \
	(VM_READ | VM_WRITE | \
	 ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
	 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
L
Linus Torvalds 已提交
254

255 256
#define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE)
#define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
L
Linus Torvalds 已提交
257

258
#include <asm-generic/memory_model.h>
259
#include <asm-generic/getorder.h>
260

L
Linus Torvalds 已提交
261
#endif /* _ASM_PAGE_H */