114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/*
214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * This file contains the routines setting up the linux page tables.
314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  -- paulus
414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *
514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  Derived from arch/ppc/mm/init.c:
614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *
814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
1014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *    Copyright (C) 1996 Paul Mackerras
1114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *
1214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  Derived from "arch/i386/mm/init.c"
1314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
1414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *
1514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  This program is free software; you can redistribute it and/or
1614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  modify it under the terms of the GNU General Public License
1714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  as published by the Free Software Foundation; either version
1814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *  2 of the License, or (at your option) any later version.
1914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras *
2014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras */
2114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
2214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/kernel.h>
2314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/module.h>
2414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/types.h>
2514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/mm.h>
2614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/vmalloc.h>
2714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/init.h>
2814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/highmem.h>
2995f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu#include <linux/memblock.h>
305a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
3114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
3214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/pgtable.h>
3314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/pgalloc.h>
342c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala#include <asm/fixmap.h>
3514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/io.h>
36ae3a197e3d0bfe3f4bf1693723e82dc018c096f3David Howells#include <asm/setup.h>
3714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
3814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include "mmu_decl.h"
3914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
4014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasunsigned long ioremap_base;
4114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasunsigned long ioremap_bot;
42920573bd03bf690135967b5022362d34ede589c3Olaf HeringEXPORT_SYMBOL(ioremap_bot);	/* aka VMALLOC_END */
4314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
44c3993f10076ae1fa479d5b3e227fe15e001c45a9Michael Ellerman#ifdef CONFIG_6xx
4514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define HAVE_BATS	1
4614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif
4714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
4814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#if defined(CONFIG_FSL_BOOKE)
4914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define HAVE_TLBCAM	1
5014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif
5114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
5214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasextern char etext[], _stext[];
5314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
5414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef HAVE_BATS
557c5c4325d2d911fe54db3bc14149bfa558ae0acbBecky Bruceextern phys_addr_t v_mapped_by_bats(unsigned long va);
567c5c4325d2d911fe54db3bc14149bfa558ae0acbBecky Bruceextern unsigned long p_mapped_by_bats(phys_addr_t pa);
577c5c4325d2d911fe54db3bc14149bfa558ae0acbBecky Brucevoid setbat(int index, unsigned long virt, phys_addr_t phys,
5814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	    unsigned int size, int flags);
5914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
6014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#else /* !HAVE_BATS */
6114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define v_mapped_by_bats(x)	(0UL)
6214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define p_mapped_by_bats(x)	(0UL)
6314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif /* HAVE_BATS */
6414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
6514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef HAVE_TLBCAM
6614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasextern unsigned int tlbcam_index;
676c24b17453c8dc444a746e45b8a404498fc9fcf7Kumar Galaextern phys_addr_t v_mapped_by_tlbcam(unsigned long va);
686c24b17453c8dc444a746e45b8a404498fc9fcf7Kumar Galaextern unsigned long p_mapped_by_tlbcam(phys_addr_t pa);
6914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#else /* !HAVE_TLBCAM */
7014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define v_mapped_by_tlbcam(x)	(0UL)
7114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define p_mapped_by_tlbcam(x)	(0UL)
7214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif /* HAVE_TLBCAM */
7314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
74ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok#define PGDIR_ORDER	(32 + PGD_T_LOG2 - PGDIR_SHIFT)
7514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
7614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerraspgd_t *pgd_alloc(struct mm_struct *mm)
7714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
7814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	pgd_t *ret;
7914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
80ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok	/* pgdir take page or two with 4K pages and a page fraction otherwise */
81ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok#ifndef CONFIG_PPC_4K_PAGES
82ae9fd31a3668ca97e8f37698b927ae7c0b70807aJesper Juhl	ret = kzalloc(1 << PGDIR_ORDER, GFP_KERNEL);
83ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok#else
84ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok	ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
85ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok			PGDIR_ORDER - PAGE_SHIFT);
86ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok#endif
8714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return ret;
8814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
8914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
905e5419734c8719cbc01af959ad9c0844002c0df5Benjamin Herrenschmidtvoid pgd_free(struct mm_struct *mm, pgd_t *pgd)
9114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
92ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok#ifndef CONFIG_PPC_4K_PAGES
93ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok	kfree((void *)pgd);
94ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok#else
95ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok	free_pages((unsigned long)pgd, PGDIR_ORDER - PAGE_SHIFT);
96ca9153a3a2a7556d091dfe080e42b0e67881fff6Ilya Yanok#endif
9714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
9814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
99f1aed92464def83fc3677cade823cad71cf5f0d4Kumar Gala__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
10014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
10114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	pte_t *pte;
10214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	extern int mem_init_done;
10314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	extern void *early_get_page(void);
10414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
10514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (mem_init_done) {
10614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
10714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} else {
10814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		pte = (pte_t *)early_get_page();
10914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (pte)
11014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			clear_page(pte);
11114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
11214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return pte;
11314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
11414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
1152f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4Martin Schwidefskypgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
11614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
11714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	struct page *ptepage;
11814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
1192f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4Martin Schwidefsky	gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
12014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
12114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	ptepage = alloc_pages(flags, 0);
1222f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4Martin Schwidefsky	if (!ptepage)
1232f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4Martin Schwidefsky		return NULL;
1244f804943f99454ac79e0f448428447f1a72d09fcKirill A. Shutemov	if (!pgtable_page_ctor(ptepage)) {
1254f804943f99454ac79e0f448428447f1a72d09fcKirill A. Shutemov		__free_page(ptepage);
1264f804943f99454ac79e0f448428447f1a72d09fcKirill A. Shutemov		return NULL;
1274f804943f99454ac79e0f448428447f1a72d09fcKirill A. Shutemov	}
12814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return ptepage;
12914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
13014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
13114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasvoid __iomem *
13214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasioremap(phys_addr_t addr, unsigned long size)
13314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
1341cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt	return __ioremap_caller(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED,
1351cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt				__builtin_return_address(0));
13614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
137920573bd03bf690135967b5022362d34ede589c3Olaf HeringEXPORT_SYMBOL(ioremap);
13814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
13914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasvoid __iomem *
140be135f40899cb3334faa7d2e27025055da311ec4Anton Blanchardioremap_wc(phys_addr_t addr, unsigned long size)
141be135f40899cb3334faa7d2e27025055da311ec4Anton Blanchard{
142be135f40899cb3334faa7d2e27025055da311ec4Anton Blanchard	return __ioremap_caller(addr, size, _PAGE_NO_CACHE,
143be135f40899cb3334faa7d2e27025055da311ec4Anton Blanchard				__builtin_return_address(0));
144be135f40899cb3334faa7d2e27025055da311ec4Anton Blanchard}
145be135f40899cb3334faa7d2e27025055da311ec4Anton BlanchardEXPORT_SYMBOL(ioremap_wc);
146be135f40899cb3334faa7d2e27025055da311ec4Anton Blanchard
147be135f40899cb3334faa7d2e27025055da311ec4Anton Blanchardvoid __iomem *
14840f1ce7fb7e8b5d4d0821c0f3dc866cb1d47d99cAnton Blanchardioremap_prot(phys_addr_t addr, unsigned long size, unsigned long flags)
14968a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidt{
150a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt	/* writeable implies dirty for kernel addresses */
151a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt	if (flags & _PAGE_RW)
152a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt		flags |= _PAGE_DIRTY | _PAGE_HWWRITE;
153a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt
154a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt	/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
155ea3cc330ac0cd521ff07c7cd432a1848c19a7e92Benjamin Herrenschmidt	flags &= ~(_PAGE_USER | _PAGE_EXEC);
156a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt
15755052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt#ifdef _PAGE_BAP_SR
15855052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt	/* _PAGE_USER contains _PAGE_BAP_SR on BookE using the new PTE format
15955052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt	 * which means that we just cleared supervisor access... oops ;-) This
16055052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt	 * restores it
16155052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt	 */
16255052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt	flags |= _PAGE_BAP_SR;
16355052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt#endif
16455052eeca6d71d76f7c3f156c0501814d8e5e6d3Benjamin Herrenschmidt
1651cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt	return __ioremap_caller(addr, size, flags, __builtin_return_address(0));
16668a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidt}
16740f1ce7fb7e8b5d4d0821c0f3dc866cb1d47d99cAnton BlanchardEXPORT_SYMBOL(ioremap_prot);
16868a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidt
16968a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidtvoid __iomem *
17014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
17114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
1721cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt	return __ioremap_caller(addr, size, flags, __builtin_return_address(0));
1731cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt}
1741cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt
1751cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidtvoid __iomem *
1761cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt__ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
1771cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt		 void *caller)
1781cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt{
17914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long v, i;
18014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	phys_addr_t p;
18114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	int err;
18214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
183a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt	/* Make sure we have the base flags */
184a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt	if ((flags & _PAGE_PRESENT) == 0)
1858d1cf34e7ad5c7738ce20d20bd7f002f562cb8b5Benjamin Herrenschmidt		flags |= PAGE_KERNEL;
186a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt
187a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt	/* Non-cacheable page cannot be coherent */
188a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt	if (flags & _PAGE_NO_CACHE)
189a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt		flags &= ~_PAGE_COHERENT;
190a1f242ff460e4b50a045fa237c3c56cce9eabf83Benjamin Herrenschmidt
19114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/*
19214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * Choose an address to map it to.
19314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * Once the vmalloc system is running, we use it.
19414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * Before then, we use space going down from ioremap_base
19514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * (ioremap_bot records where we're up to).
19614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 */
19714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	p = addr & PAGE_MASK;
19814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	size = PAGE_ALIGN(addr + size) - p;
19914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
20014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/*
20114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * If the address lies within the first 16 MB, assume it's in ISA
20214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * memory space
20314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 */
20414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (p < 16*1024*1024)
20514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		p += _ISA_MEM_BASE;
20614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
20701695a9687e5a8d78589605037cc7828a5b67ac9Anton Vorontsov#ifndef CONFIG_CRASH_DUMP
20814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/*
20914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * Don't allow anybody to remap normal RAM that we're using.
21014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * mem_init() sets high_memory so only do the check after that.
21114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 */
212c5df7f775148723de39274537a886e9502eef336Albert Herranz	if (mem_init_done && (p < virt_to_phys(high_memory)) &&
21395f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu	    !(__allow_ioremap_reserved && memblock_is_region_reserved(p, size))) {
214a2234b4baefe2a2742b5fa8839be1ab1aca39057Joe Perches		printk("__ioremap(): phys addr 0x%llx is RAM lr %pf\n",
21537f01d64d83705f82bb06eac8134acc8ef665565David Gibson		       (unsigned long long)p, __builtin_return_address(0));
21614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return NULL;
21714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
21801695a9687e5a8d78589605037cc7828a5b67ac9Anton Vorontsov#endif
21914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
22014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (size == 0)
22114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return NULL;
22214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
22314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/*
22414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * Is it already mapped?  Perhaps overlapped by a previous
22514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * BAT mapping.  If the whole area is mapped then we're done,
22614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * otherwise remap it since we want to keep the virt addrs for
22714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * each request contiguous.
22814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 *
22914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * We make the assumption here that if the bottom and top
23014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * of the range we want are mapped then it's mapped to the
23114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * same virt address (and this is contiguous).
23214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 *  -- Cort
23314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 */
23414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
23514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		goto out;
23614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
23714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if ((v = p_mapped_by_tlbcam(p)))
23814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		goto out;
23914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
24014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (mem_init_done) {
24114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		struct vm_struct *area;
2421cdab55d8a8313f77a95fb8ca966dc4334f8e810Benjamin Herrenschmidt		area = get_vm_area_caller(size, VM_IOREMAP, caller);
24314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (area == 0)
24414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			return NULL;
2457a9d12568e34e37a72d9e00ce01b62dec527e663Michael Ellerman		area->phys_addr = p;
24614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		v = (unsigned long) area->addr;
24714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} else {
24814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		v = (ioremap_bot -= size);
24914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
25014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
25114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/*
25214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * Should check if it is a candidate for a BAT mapping
25314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 */
25414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
25514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	err = 0;
25614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	for (i = 0; i < size && err == 0; i += PAGE_SIZE)
25714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		err = map_page(v+i, p+i, flags);
25814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (err) {
25914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (mem_init_done)
26014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			vunmap((void *)v);
26114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return NULL;
26214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
26314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
26414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasout:
26514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK));
26614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
267920573bd03bf690135967b5022362d34ede589c3Olaf HeringEXPORT_SYMBOL(__ioremap);
26814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
26914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasvoid iounmap(volatile void __iomem *addr)
27014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
27114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/*
27214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * If mapped by BATs then there is nothing to do.
27314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 * Calling vfree() generates a benign warning.
27414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	 */
27514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (v_mapped_by_bats((unsigned long)addr)) return;
27614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
27714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (addr > high_memory && (unsigned long) addr < ioremap_bot)
27814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		vunmap((void *) (PAGE_MASK & (unsigned long)addr));
27914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
280920573bd03bf690135967b5022362d34ede589c3Olaf HeringEXPORT_SYMBOL(iounmap);
28114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
28268a64357d15ae4f596e92715719071952006e83cBenjamin Herrenschmidtint map_page(unsigned long va, phys_addr_t pa, int flags)
28314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
28414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	pmd_t *pd;
28514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	pte_t *pg;
28614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	int err = -ENOMEM;
28714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
28814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/* Use upper 10 bits of VA to index the first level map */
289d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson	pd = pmd_offset(pud_offset(pgd_offset_k(va), va), va);
29014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/* Use middle 10 bits of VA to index the second-level map */
291e2f2e58e7968f8446b1078a20a18bf8ea12b4fbcPaul Mackerras	pg = pte_alloc_kernel(pd, va);
29214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (pg != 0) {
29314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		err = 0;
2943be4e6990edf65624cfcbf8f7e33810626b2eefaBenjamin Herrenschmidt		/* The PTE should never be already set nor present in the
2953be4e6990edf65624cfcbf8f7e33810626b2eefaBenjamin Herrenschmidt		 * hash table
2963be4e6990edf65624cfcbf8f7e33810626b2eefaBenjamin Herrenschmidt		 */
2977021d86afa6f3a8bf76218ac97f5847a6d985730Anton Vorontsov		BUG_ON((pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)) &&
2987021d86afa6f3a8bf76218ac97f5847a6d985730Anton Vorontsov		       flags);
2993be4e6990edf65624cfcbf8f7e33810626b2eefaBenjamin Herrenschmidt		set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT,
3003be4e6990edf65624cfcbf8f7e33810626b2eefaBenjamin Herrenschmidt						     __pgprot(flags)));
30114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
30247ce8af4209f4344f152aa6fc538efe9d6bdfd1aScott Wood	smp_wmb();
30314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return err;
30414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
30514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
30614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/*
307de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz * Map in a chunk of physical memory starting at start.
30814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras */
309de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranzvoid __init __mapin_ram_chunk(unsigned long offset, unsigned long top)
31014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
31199c62dd773797b68f3b1ca6bb3274725d1852fa2Kumar Gala	unsigned long v, s, f;
31299c62dd773797b68f3b1ca6bb3274725d1852fa2Kumar Gala	phys_addr_t p;
313ee4f2ea48674b6c9d91bc854edc51a3e6a7168c4Benjamin Herrenschmidt	int ktext;
31414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
315de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	s = offset;
316ccdcef72c249c289898b164eada89a61855b9287Dale Farnsworth	v = PAGE_OFFSET + s;
31799c62dd773797b68f3b1ca6bb3274725d1852fa2Kumar Gala	p = memstart_addr + s;
318de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	for (; s < top; s += PAGE_SIZE) {
319ee4f2ea48674b6c9d91bc854edc51a3e6a7168c4Benjamin Herrenschmidt		ktext = ((char *) v >= _stext && (char *) v < etext);
3208d1cf34e7ad5c7738ce20d20bd7f002f562cb8b5Benjamin Herrenschmidt		f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL;
32114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		map_page(v, p, f);
322ee4f2ea48674b6c9d91bc854edc51a3e6a7168c4Benjamin Herrenschmidt#ifdef CONFIG_PPC_STD_MMU_32
323ee4f2ea48674b6c9d91bc854edc51a3e6a7168c4Benjamin Herrenschmidt		if (ktext)
324ee4f2ea48674b6c9d91bc854edc51a3e6a7168c4Benjamin Herrenschmidt			hash_preload(&init_mm, v, 0, 0x300);
325ee4f2ea48674b6c9d91bc854edc51a3e6a7168c4Benjamin Herrenschmidt#endif
32614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		v += PAGE_SIZE;
32714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		p += PAGE_SIZE;
32814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
32914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
33014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
331de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranzvoid __init mapin_ram(void)
332de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz{
333de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	unsigned long s, top;
334de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz
335de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz#ifndef CONFIG_WII
336de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	top = total_lowmem;
337de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	s = mmu_mapin_ram(top);
338de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	__mapin_ram_chunk(s, top);
339de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz#else
340de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	if (!wii_hole_size) {
341de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz		s = mmu_mapin_ram(total_lowmem);
342de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz		__mapin_ram_chunk(s, total_lowmem);
343de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	} else {
344de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz		top = wii_hole_start;
345de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz		s = mmu_mapin_ram(top);
346de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz		__mapin_ram_chunk(s, top);
347de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz
34895f72d1ed41a66f1c1c29c24d479de81a0bea36fYinghai Lu		top = memblock_end_of_DRAM();
349de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz		s = wii_mmu_mapin_mem2(top);
350de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz		__mapin_ram_chunk(s, top);
351de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz	}
352de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz#endif
353de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz}
354de32400dd26e743c5d500aa42d8d6818b79edb73Albert Herranz
35514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/* Scan the real Linux page tables and return a PTE pointer for
35614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * a virtual address in a context.
35714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * Returns true (1) if PTE was found, zero otherwise.  The pointer to
35814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * the PTE pointer is unmodified if PTE is not found.
35914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras */
36014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasint
361bab70a4af737f623de5b034976a311055308ab86Eugene Suroveginget_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
36214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
36314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        pgd_t	*pgd;
364d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson	pud_t	*pud;
36514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        pmd_t	*pmd;
36614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        pte_t	*pte;
36714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        int     retval = 0;
36814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
36914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        pgd = pgd_offset(mm, addr & PAGE_MASK);
37014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        if (pgd) {
371d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson		pud = pud_offset(pgd, addr & PAGE_MASK);
372d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson		if (pud && pud_present(*pud)) {
373d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson			pmd = pmd_offset(pud, addr & PAGE_MASK);
374d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson			if (pmd_present(*pmd)) {
375d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson				pte = pte_offset_map(pmd, addr & PAGE_MASK);
376d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson				if (pte) {
377d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson					retval = 1;
378d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson					*ptep = pte;
379d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson					if (pmdp)
380d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson						*pmdp = pmd;
381d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson					/* XXX caller needs to do pte_unmap, yuck */
382d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson				}
383d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson			}
384d1953c8888ef034b912ee33bc2ea2cce6a414402David Gibson		}
38514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        }
38614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras        return(retval);
38714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
38814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
38988df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt#ifdef CONFIG_DEBUG_PAGEALLOC
39088df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
39188df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidtstatic int __change_page_attr(struct page *page, pgprot_t prot)
39288df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt{
39388df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	pte_t *kpte;
39488df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	pmd_t *kpmd;
39588df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	unsigned long address;
39688df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
39788df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	BUG_ON(PageHighMem(page));
39888df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	address = (unsigned long)page_address(page);
39988df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
40088df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address))
40188df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt		return 0;
40288df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	if (!get_pteptr(&init_mm, address, &kpte, &kpmd))
40388df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt		return -EINVAL;
40450891457f1001450be61be0861b2b49abdcb5fb9Benjamin Herrenschmidt	__set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0);
40588df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	wmb();
406f63837f0581fe580168ae1a7d178ded935411747Benjamin Herrenschmidt	flush_tlb_page(NULL, address);
40788df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	pte_unmap(kpte);
40888df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
40988df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	return 0;
41088df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt}
41188df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
41288df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt/*
41388df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt * Change the page attributes of an page in the linear mapping.
41488df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt *
41588df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt * THIS CONFLICTS WITH BAT MAPPINGS, DEBUG USE ONLY
41688df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt */
41788df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidtstatic int change_page_attr(struct page *page, int numpages, pgprot_t prot)
41888df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt{
41988df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	int i, err = 0;
42088df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	unsigned long flags;
42188df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
42288df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	local_irq_save(flags);
42388df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	for (i = 0; i < numpages; i++, page++) {
42488df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt		err = __change_page_attr(page, prot);
42588df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt		if (err)
42688df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt			break;
42788df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	}
42888df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	local_irq_restore(flags);
42988df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	return err;
43088df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt}
43188df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
43288df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
43388df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidtvoid kernel_map_pages(struct page *page, int numpages, int enable)
43488df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt{
43588df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	if (PageHighMem(page))
43688df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt		return;
43788df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt
43888df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt	change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
43988df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt}
44088df6e90fa9782dbf44d936e44649afe271e4790Benjamin Herrenschmidt#endif /* CONFIG_DEBUG_PAGEALLOC */
4412c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala
4422c419bdeca1d958bb02228b5141695f312d8c633Kumar Galastatic int fixmaps;
4432c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala
4442c419bdeca1d958bb02228b5141695f312d8c633Kumar Galavoid __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
4452c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala{
4462c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala	unsigned long address = __fix_to_virt(idx);
4472c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala
4482c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala	if (idx >= __end_of_fixed_addresses) {
4492c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala		BUG();
4502c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala		return;
4512c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala	}
4522c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala
45346a7417963a84f67984af1af59d43261159dd96bDavid Gibson	map_page(address, phys, pgprot_val(flags));
4542c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala	fixmaps++;
4552c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala}
4562c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala
4572c419bdeca1d958bb02228b5141695f312d8c633Kumar Galavoid __this_fixmap_does_not_exist(void)
4582c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala{
4592c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala	WARN_ON(1);
4602c419bdeca1d958bb02228b5141695f312d8c633Kumar Gala}
461