11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * srmmu.c:  SRMMU specific routines for memory management.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995,2002 Pete Zaitcev (zaitcev@yahoo.com)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999,2000 Anton Blanchard (anton@samba.org)
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
114a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <linux/seq_file.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h>
144a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <linux/pagemap.h>
154a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <linux/vmalloc.h>
161eeb66a1bb973534dc3d064920a5ca683823372eChristoph Hellwig#include <linux/kdebug.h>
17a56b072fa357ab076cb6c9b52e58fbe3c709da10Paul Gortmaker#include <linux/export.h>
184a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <linux/kernel.h>
194a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <linux/init.h>
20949e82744b31b555dd6dba40758e05338f305233Robert P. J. Day#include <linux/log2.h>
215a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
224a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <linux/fs.h>
234a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <linux/mm.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
254a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/mmu_context.h>
264a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/cacheflush.h>
274a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/tlbflush.h>
284a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/io-unit.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgalloc.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h>
314a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/bitext.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/vaddrs.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cache.h>
344a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/traps.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/oplib.h>
364a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/mbus.h>
374a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/page.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/asi.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/msi.h>
404a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/smp.h>
414a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/io.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Now the cpu specific definitions. */
444a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/turbosparc.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/tsunami.h>
464a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/viking.h>
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/swift.h>
4875d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele#include <asm/leon.h>
494a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/mxcc.h>
504a049b03412712d968f38176ff128f4998174d45Sam Ravnborg#include <asm/ross.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52ddb7417ea9d31b9ef34c28cfe9c31da3d18c376aSam Ravnborg#include "mm_32.h"
53accf032cfa582ed95da130b06241637659210edbSam Ravnborg
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum mbus_module srmmu_modtype;
5550215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic unsigned int hwbug_bitmask;
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vac_cache_size;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vac_line_size;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct resource sparc_iomap;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned long last_valid_pfn;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6350215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic pgd_t *srmmu_swapper_pg_dir;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
655d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerconst struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
66a56b072fa357ab076cb6c9b52e58fbe3c709da10Paul GortmakerEXPORT_SYMBOL(sparc32_cachetlb_ops);
675d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
695d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerconst struct sparc32_cachetlb_ops *local_ops;
705d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FLUSH_BEGIN(mm)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FLUSH_END
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
745d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller#define FLUSH_BEGIN(mm) if ((mm)->context != NO_CONTEXT) {
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FLUSH_END	}
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint flush_page_for_dma_global = 1;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *srmmu_name;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsctxd_t *srmmu_ctx_table_phys;
8350215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic ctxd_t *srmmu_context_table;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint viking_mxcc_present;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(srmmu_context_spinlock);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8850215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic int is_hypersparc;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9050215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic int srmmu_cache_pagetables;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* these will be initialized in srmmu_nocache_calcsize() */
9350215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic unsigned long srmmu_nocache_size;
9450215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic unsigned long srmmu_nocache_end;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1 bit <=> 256 bytes of nocache <=> 64 PTEs */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The context table is a nocache user with the biggest alignment needs. */
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SRMMU_NOCACHE_ALIGN_MAX (sizeof(ctxd_t)*SRMMU_MAX_CONTEXTS)
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid *srmmu_nocache_pool;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct bit_map srmmu_nocache_map;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int srmmu_pmd_none(pmd_t pmd)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ return !(pmd_val(pmd) & 0xFFFFFFF); }
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* XXX should we hyper_flush_whole_icache here - Anton */
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
11062875cff73fbb7c22bdb96e42d2e78cfe8464e06David S. Miller{ set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); }
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
112642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborgvoid pmd_set(pmd_t *pmdp, pte_t *ptep)
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long ptp;	/* Physical address, shifted right by 4 */
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptp = __nocache_pa((unsigned long) ptep) >> 4;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
11962875cff73fbb7c22bdb96e42d2e78cfe8464e06David S. Miller		set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
124642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborgvoid pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long ptp;	/* Physical address, shifted right by 4 */
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4);	/* watch for overflow */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
13162875cff73fbb7c22bdb96e42d2e78cfe8464e06David S. Miller		set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
136605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg/* Find an entry in the third-level page table.. */
137605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborgpte_t *pte_offset_kernel(pmd_t *dir, unsigned long address)
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *pte;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte = __nocache_va((dir->pmdv[0] & SRMMU_PTD_PMASK) << 4);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (pte_t *) pte +
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * size: bytes to allocate in the nocache area.
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * align: bytes, number to align at.
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the virtual address of the allocated area.
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
151f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborgstatic void *__srmmu_get_nocache(int size, int align)
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int offset;
154f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	unsigned long addr;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (size < SRMMU_NOCACHE_BITMAP_SHIFT) {
157f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		printk(KERN_ERR "Size 0x%x too small for nocache request\n",
158f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		       size);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size = SRMMU_NOCACHE_BITMAP_SHIFT;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
161f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	if (size & (SRMMU_NOCACHE_BITMAP_SHIFT - 1)) {
162f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		printk(KERN_ERR "Size 0x%x unaligned int nocache request\n",
163f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		       size);
164f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		size += SRMMU_NOCACHE_BITMAP_SHIFT - 1;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG_ON(align > SRMMU_NOCACHE_ALIGN_MAX);
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	offset = bit_map_string_get(&srmmu_nocache_map,
169f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg				    size >> SRMMU_NOCACHE_BITMAP_SHIFT,
170f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg				    align >> SRMMU_NOCACHE_BITMAP_SHIFT);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (offset == -1) {
172f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		printk(KERN_ERR "srmmu: out of nocache %d: %d/%d\n",
173f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		       size, (int) srmmu_nocache_size,
174f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		       srmmu_nocache_map.used << SRMMU_NOCACHE_BITMAP_SHIFT);
175e8c29c839b5c9f6704c7105e1248b476e8f4c04eSam Ravnborg		return NULL;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
178f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	addr = SRMMU_NOCACHE_VADDR + (offset << SRMMU_NOCACHE_BITMAP_SHIFT);
179f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	return (void *)addr;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
182f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborgvoid *srmmu_get_nocache(int size, int align)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
184f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	void *tmp;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = __srmmu_get_nocache(size, align);
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tmp)
189f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg		memset(tmp, 0, size);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return tmp;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
194f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborgvoid srmmu_free_nocache(void *addr, int size)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
196f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	unsigned long vaddr;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int offset;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
199f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	vaddr = (unsigned long)addr;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vaddr < SRMMU_NOCACHE_VADDR) {
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Vaddr %lx is smaller than nocache base 0x%lx\n",
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    vaddr, (unsigned long)SRMMU_NOCACHE_VADDR);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
205605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (vaddr + size > srmmu_nocache_end) {
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Vaddr %lx is bigger than nocache end 0x%lx\n",
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    vaddr, srmmu_nocache_end);
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
210949e82744b31b555dd6dba40758e05338f305233Robert P. J. Day	if (!is_power_of_2(size)) {
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Size 0x%x is not a power of 2\n", size);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (size < SRMMU_NOCACHE_BITMAP_SHIFT) {
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Size 0x%x is too small\n", size);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
218605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (vaddr & (size - 1)) {
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Vaddr %lx is not aligned to size 0x%x\n", vaddr, size);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	offset = (vaddr - SRMMU_NOCACHE_VADDR) >> SRMMU_NOCACHE_BITMAP_SHIFT;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = size >> SRMMU_NOCACHE_BITMAP_SHIFT;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bit_map_clear(&srmmu_nocache_map, offset, size);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22950215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic void srmmu_early_allocate_ptable_skeleton(unsigned long start,
23050215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunk						 unsigned long end);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
232d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg/* Return how much physical memory we have.  */
233d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborgstatic unsigned long __init probe_memory(void)
234d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg{
235d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg	unsigned long total = 0;
236d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg	int i;
237d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg
238d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg	for (i = 0; sp_banks[i].num_bytes; i++)
239d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg		total += sp_banks[i].num_bytes;
240d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg
241d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg	return total;
242d8a1b2b94ca5fe219b3c77389e2424145c24c668Sam Ravnborg}
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reserve nocache dynamically proportionally to the amount of
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * system RAM. -- Tomas Szepe <szepe@pinerecords.com>, June 2002
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
24832442467ed58ba7d32d02a27146650b9a4763b5dSam Ravnborgstatic void __init srmmu_nocache_calcsize(void)
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long sysmemavail = probe_memory() / 1024;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int srmmu_nocache_npages;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_nocache_npages =
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sysmemavail / SRMMU_NOCACHE_ALCRATIO / 1024 * 256;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* P3 XXX The 4x overuse: corroborated by /proc/meminfo. */
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// if (srmmu_nocache_npages < 256) srmmu_nocache_npages = 256;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (srmmu_nocache_npages < SRMMU_MIN_NOCACHE_PAGES)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_nocache_npages = SRMMU_MIN_NOCACHE_PAGES;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* anything above 1280 blows up */
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (srmmu_nocache_npages > SRMMU_MAX_NOCACHE_PAGES)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_nocache_npages = SRMMU_MAX_NOCACHE_PAGES;
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_nocache_size = srmmu_nocache_npages * PAGE_SIZE;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_nocache_end = SRMMU_NOCACHE_VADDR + srmmu_nocache_size;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26950215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic void __init srmmu_nocache_init(void)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
271e8c29c839b5c9f6704c7105e1248b476e8f4c04eSam Ravnborg	void *srmmu_nocache_bitmap;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int bitmap_bits;
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgd;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pmd_t *pmd;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte_t *pte;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long paddr, vaddr;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long pteval;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bitmap_bits = srmmu_nocache_size >> SRMMU_NOCACHE_BITMAP_SHIFT;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_nocache_pool = __alloc_bootmem(srmmu_nocache_size,
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		SRMMU_NOCACHE_ALIGN_MAX, 0UL);
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28554df2db36c93bbb8c757f172d97c577040de6abbAkinobu Mita	srmmu_nocache_bitmap =
28654df2db36c93bbb8c757f172d97c577040de6abbAkinobu Mita		__alloc_bootmem(BITS_TO_LONGS(bitmap_bits) * sizeof(long),
28754df2db36c93bbb8c757f172d97c577040de6abbAkinobu Mita				SMP_CACHE_BYTES, 0UL);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bit_map_init(&srmmu_nocache_map, srmmu_nocache_bitmap, bitmap_bits);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
290f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	srmmu_swapper_pg_dir = __srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(__nocache_fix(srmmu_swapper_pg_dir), 0, SRMMU_PGD_TABLE_SIZE);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_mm.pgd = srmmu_swapper_pg_dir;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, srmmu_nocache_end);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	paddr = __pa((unsigned long)srmmu_nocache_pool);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vaddr = SRMMU_NOCACHE_VADDR;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (vaddr < srmmu_nocache_end) {
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pgd = pgd_offset_k(vaddr);
3019701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg		pmd = pmd_offset(__nocache_fix(pgd), vaddr);
3029701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg		pte = pte_offset_kernel(__nocache_fix(pmd), vaddr);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pteval = ((paddr >> 4) | SRMMU_ET_PTE | SRMMU_PRIV);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (srmmu_cache_pagetables)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pteval |= SRMMU_CACHE;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30962875cff73fbb7c22bdb96e42d2e78cfe8464e06David S. Miller		set_pte(__nocache_fix(pte), __pte(pteval));
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vaddr += PAGE_SIZE;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		paddr += PAGE_SIZE;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_cache_all();
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_tlb_all();
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
319642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborgpgd_t *get_pgd_fast(void)
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgd = NULL;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
323f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	pgd = __srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pgd) {
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pgd_t *init = pgd_offset_k(0);
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return pgd;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Hardware needs alignment to 256 only, but we align to whole page size
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to reduce fragmentation problems due to the buddy principle.
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX Provide actual fragmentation statistics in /proc.
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Alignments up to the page size are the same for physical and virtual
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * addresses of the nocache area.
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
342642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborgpgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long pte;
3452f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4Martin Schwidefsky	struct page *page;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
347642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborg	if ((pte = (unsigned long)pte_alloc_one_kernel(mm, address)) == 0)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
349605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	page = pfn_to_page(__nocache_pa(pte) >> PAGE_SHIFT);
3501ae9ae5f7df726c67736c643c1f03f7bdfe748ebKirill A. Shutemov	if (!pgtable_page_ctor(page)) {
3511ae9ae5f7df726c67736c643c1f03f7bdfe748ebKirill A. Shutemov		__free_page(page);
3521ae9ae5f7df726c67736c643c1f03f7bdfe748ebKirill A. Shutemov		return NULL;
3531ae9ae5f7df726c67736c643c1f03f7bdfe748ebKirill A. Shutemov	}
3542f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4Martin Schwidefsky	return page;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
357642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborgvoid pte_free(struct mm_struct *mm, pgtable_t pte)
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long p;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3612f569afd9ced9ebec9a6eb3dbf6f83429be0a7b4Martin Schwidefsky	pgtable_page_dtor(pte);
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = (unsigned long)page_address(pte);	/* Cached address (for test) */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (p == 0)
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = page_to_pfn(pte) << PAGE_SHIFT;	/* Physical address */
366f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg
367f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	/* free non cached virtual address*/
368f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	srmmu_free_nocache(__nocache_va(p), PTE_SIZE);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg/* context handling - a dynamically sized pool is used */
372b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg#define NO_CONTEXT	-1
373b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
374b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstruct ctx_list {
375b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	struct ctx_list *next;
376b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	struct ctx_list *prev;
377b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	unsigned int ctx_number;
378b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	struct mm_struct *ctx_mm;
379b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg};
380b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
381b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstatic struct ctx_list *ctx_list_pool;
382b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstatic struct ctx_list ctx_free;
383b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstatic struct ctx_list ctx_used;
384b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
385b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg/* At boot time we determine the number of contexts */
386b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstatic int num_contexts;
387b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
388b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstatic inline void remove_from_ctx_list(struct ctx_list *entry)
389b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg{
390b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	entry->next->prev = entry->prev;
391b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	entry->prev->next = entry->next;
392b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg}
393b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
394b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstatic inline void add_to_ctx_list(struct ctx_list *head, struct ctx_list *entry)
395b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg{
396b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	entry->next = head;
397b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	(entry->prev = head->prev)->next = entry;
398b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	head->prev = entry;
399b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg}
400b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg#define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry)
401b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg#define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry)
402b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
403b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void alloc_context(struct mm_struct *old_mm, struct mm_struct *mm)
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ctx_list *ctxp;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctxp = ctx_free.next;
409605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (ctxp != &ctx_free) {
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		remove_from_ctx_list(ctxp);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		add_to_used_ctxlist(ctxp);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mm->context = ctxp->ctx_number;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctxp->ctx_mm = mm;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctxp = ctx_used.next;
417605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (ctxp->ctx_mm == old_mm)
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctxp = ctxp->next;
419605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (ctxp == &ctx_used)
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("out of mmu contexts");
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_cache_mm(ctxp->ctx_mm);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_tlb_mm(ctxp->ctx_mm);
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	remove_from_ctx_list(ctxp);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_to_used_ctxlist(ctxp);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctxp->ctx_mm->context = NO_CONTEXT;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctxp->ctx_mm = mm;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mm->context = ctxp->ctx_number;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void free_context(int context)
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ctx_list *ctx_old;
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctx_old = ctx_list_pool + context;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	remove_from_ctx_list(ctx_old);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_to_free_ctxlist(ctx_old);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
439b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgstatic void __init sparc_context_init(int numctx)
440b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg{
441b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	int ctx;
442b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	unsigned long size;
443b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
444b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	size = numctx * sizeof(struct ctx_list);
445b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	ctx_list_pool = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
446b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
447b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	for (ctx = 0; ctx < numctx; ctx++) {
448b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg		struct ctx_list *clist;
449b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
450b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg		clist = (ctx_list_pool + ctx);
451b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg		clist->ctx_number = ctx;
452b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg		clist->ctx_mm = NULL;
453b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	}
454b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	ctx_free.next = ctx_free.prev = &ctx_free;
455b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	ctx_used.next = ctx_used.prev = &ctx_used;
456b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	for (ctx = 0; ctx < numctx; ctx++)
457b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg		add_to_free_ctxlist(ctx_list_pool + ctx);
458b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46034d4accfe0ed62d3a8e3dc28eec193d6085f9563Sam Ravnborgvoid switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
46134d4accfe0ed62d3a8e3dc28eec193d6085f9563Sam Ravnborg	       struct task_struct *tsk)
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
463605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (mm->context == NO_CONTEXT) {
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock(&srmmu_context_spinlock);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alloc_context(old_mm, mm);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&srmmu_context_spinlock);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_ctxd_set(&srmmu_context_table[mm->context], mm->pgd);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47075d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele	if (sparc_cpu_model == sparc_leon)
47175d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele		leon_switch_mm();
47275d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (is_hypersparc)
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hyper_flush_whole_icache();
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_context(mm->context);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Low level IO area allocation on the SRMMU. */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void srmmu_mapioaddr(unsigned long physaddr,
481605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg				   unsigned long virt_addr, int bus_type)
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgdp;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pmd_t *pmdp;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte_t *ptep;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long tmp;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	physaddr &= PAGE_MASK;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgdp = pgd_offset_k(virt_addr);
4909701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg	pmdp = pmd_offset(pgdp, virt_addr);
4919701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg	ptep = pte_offset_kernel(pmdp, virt_addr);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = (physaddr >> 4) | SRMMU_ET_PTE;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
494605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	/* I need to test whether this is consistent over all
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * sun4m's.  The bus_type represents the upper 4 bits of
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 36-bit physical address on the I/O space lines...
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp |= (bus_type << 28);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp |= SRMMU_PRIV;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__flush_page_to_ram(virt_addr);
50162875cff73fbb7c22bdb96e42d2e78cfe8464e06David S. Miller	set_pte(ptep, __pte(tmp));
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5049701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborgvoid srmmu_mapiorange(unsigned int bus, unsigned long xpa,
5059701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg		      unsigned long xva, unsigned int len)
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (len != 0) {
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len -= PAGE_SIZE;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_mapioaddr(xpa, xva, bus);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xva += PAGE_SIZE;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xpa += PAGE_SIZE;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_tlb_all();
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void srmmu_unmapioaddr(unsigned long virt_addr)
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgdp;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pmd_t *pmdp;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte_t *ptep;
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgdp = pgd_offset_k(virt_addr);
5239701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg	pmdp = pmd_offset(pgdp, virt_addr);
5249701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg	ptep = pte_offset_kernel(pmdp, virt_addr);
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No need to flush uncacheable page. */
527a46d6056f6585b1afefde190ae78ea894d720693David S. Miller	__pte_clear(ptep);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5309701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborgvoid srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (len != 0) {
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len -= PAGE_SIZE;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_unmapioaddr(virt_addr);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		virt_addr += PAGE_SIZE;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_tlb_all();
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tsunami.S */
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_cache_all(void);
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_cache_mm(struct mm_struct *mm);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_page_to_ram(unsigned long page);
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_page_for_dma(unsigned long page);
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_tlb_all(void);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_tlb_mm(struct mm_struct *mm);
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void tsunami_setup_blockops(void);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* swift.S */
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_cache_all(void);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_cache_mm(struct mm_struct *mm);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_cache_range(struct vm_area_struct *vma,
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    unsigned long start, unsigned long end);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_page_to_ram(unsigned long page);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_page_for_dma(unsigned long page);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_tlb_all(void);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_tlb_mm(struct mm_struct *mm);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_tlb_range(struct vm_area_struct *vma,
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  unsigned long start, unsigned long end);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0  /* P3: deadwood to debug precise flushes on Swift. */
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cctx, ctx1;
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	page &= PAGE_MASK;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ctx1 = vma->vm_mm->context) != -1) {
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cctx = srmmu_get_context();
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Is context # ever different from current context? P3 */
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cctx != ctx1) {
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("flush ctx %02x curr %02x\n", ctx1, cctx);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			srmmu_set_context(ctx1);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			swift_flush_page(page);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"r" (page), "i" (ASI_M_FLUSH_PROBE));
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			srmmu_set_context(cctx);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 /* Rm. prot. bits from virt. c. */
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* swift_flush_cache_all(); */
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* swift_flush_cache_page(vma, page); */
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			swift_flush_page(page);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"r" (page), "i" (ASI_M_FLUSH_PROBE));
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* same as above: srmmu_flush_tlb_page() */
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The following are all MBUS based SRMMU modules, and therefore could
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * be found in a multiprocessor configuration.  On the whole, these
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * chips seems to be much more touchy about DVMA and page tables
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with respect to cache coherency.
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* viking.S */
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_cache_all(void);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_cache_mm(struct mm_struct *mm);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     unsigned long end);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_page_to_ram(unsigned long page);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_page_for_dma(unsigned long page);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_sig_insns(struct mm_struct *mm, unsigned long addr);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_page(unsigned long page);
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_mxcc_flush_page(unsigned long page);
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_tlb_all(void);
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_tlb_mm(struct mm_struct *mm);
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   unsigned long end);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void viking_flush_tlb_page(struct vm_area_struct *vma,
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  unsigned long page);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sun4dsmp_flush_tlb_all(void);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sun4dsmp_flush_tlb_mm(struct mm_struct *mm);
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sun4dsmp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   unsigned long end);
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sun4dsmp_flush_tlb_page(struct vm_area_struct *vma,
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  unsigned long page);
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hypersparc.S */
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_cache_all(void);
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_cache_mm(struct mm_struct *mm);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_page_to_ram(unsigned long page);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_page_for_dma(unsigned long page);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_tlb_all(void);
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_tlb_mm(struct mm_struct *mm);
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void hypersparc_setup_blockops(void);
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: All of this startup code assumes the low 16mb (approx.) of
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       kernel mappings are done with one single contiguous chunk of
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       ram.  On small ram machines (classics mainly) we only get
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       around 8mb mapped for us.
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65150215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic void __init early_pgtable_allocfail(char *type)
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	prom_halt();
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65750215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic void __init srmmu_early_allocate_ptable_skeleton(unsigned long start,
65850215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunk							unsigned long end)
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgdp;
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pmd_t *pmdp;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte_t *ptep;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
664605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	while (start < end) {
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pgdp = pgd_offset_k(start);
6667d9fa4aa3d41e82d5d52612d07211ee243df3a20David S. Miller		if (pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
667f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg			pmdp = __srmmu_get_nocache(
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (pmdp == NULL)
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				early_pgtable_allocfail("pmd");
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE);
672642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborg			pgd_set(__nocache_fix(pgdp), pmdp);
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6749701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg		pmdp = pmd_offset(__nocache_fix(pgdp), start);
675605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
676f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg			ptep = __srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ptep == NULL)
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				early_pgtable_allocfail("pte");
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memset(__nocache_fix(ptep), 0, PTE_SIZE);
680642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborg			pmd_set(__nocache_fix(pmdp), ptep);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start > (0xffffffffUL - PMD_SIZE))
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start = (start + PMD_SIZE) & PMD_MASK;
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
68850215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic void __init srmmu_allocate_ptable_skeleton(unsigned long start,
68950215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunk						  unsigned long end)
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgdp;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pmd_t *pmdp;
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte_t *ptep;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
695605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	while (start < end) {
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pgdp = pgd_offset_k(start);
6977d9fa4aa3d41e82d5d52612d07211ee243df3a20David S. Miller		if (pgd_none(*pgdp)) {
698f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg			pmdp = __srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (pmdp == NULL)
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				early_pgtable_allocfail("pmd");
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE);
702642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborg			pgd_set(pgdp, pmdp);
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7049701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg		pmdp = pmd_offset(pgdp, start);
705605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (srmmu_pmd_none(*pmdp)) {
706f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg			ptep = __srmmu_get_nocache(PTE_SIZE,
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							     PTE_SIZE);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ptep == NULL)
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				early_pgtable_allocfail("pte");
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memset(ptep, 0, PTE_SIZE);
711642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborg			pmd_set(pmdp, ptep);
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start > (0xffffffffUL - PMD_SIZE))
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start = (start + PMD_SIZE) & PMD_MASK;
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
719805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg/* These flush types are not available on all chips... */
720805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborgstatic inline unsigned long srmmu_probe(unsigned long vaddr)
721805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg{
722805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg	unsigned long retval;
723805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg
724805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg	if (sparc_cpu_model != sparc_leon) {
725805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg
726805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg		vaddr &= PAGE_MASK;
727805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg		__asm__ __volatile__("lda [%1] %2, %0\n\t" :
728805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg				     "=r" (retval) :
729805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg				     "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
730805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg	} else {
731e8c29c839b5c9f6704c7105e1248b476e8f4c04eSam Ravnborg		retval = leon_swprobe(vaddr, NULL);
732805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg	}
733805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg	return retval;
734805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg}
735805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is much cleaner than poking around physical address space
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * looking at the prom's page table directly which is what most
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other OS's do.  Yuck... this is much better.
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
74150215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunkstatic void __init srmmu_inherit_prom_mappings(unsigned long start,
74250215d6511265d46ba14038640b16c5dd7731ff4Adrian Bunk					       unsigned long end)
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7447cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg	unsigned long probed;
7457cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg	unsigned long addr;
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgdp;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pmd_t *pmdp;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte_t *ptep;
7497cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg	int what; /* 0 = normal-pte, 1 = pmd-level pte, 2 = pgd-level pte */
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	while (start <= end) {
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start == 0)
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break; /* probably wrap around */
754605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (start == 0xfef00000)
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start = KADB_DEBUGGER_BEGVM;
7567cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg		probed = srmmu_probe(start);
7577cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg		if (!probed) {
7587cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			/* continue probing until we find an entry */
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start += PAGE_SIZE;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
762605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* A red snapper, see what it really is. */
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		what = 0;
7657cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg		addr = start - PAGE_SIZE;
766605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
767605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (!(start & ~(SRMMU_REAL_PMD_MASK))) {
7687cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			if (srmmu_probe(addr + SRMMU_REAL_PMD_SIZE) == probed)
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				what = 1;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
771605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
772605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (!(start & ~(SRMMU_PGDIR_MASK))) {
7737cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			if (srmmu_probe(addr + SRMMU_PGDIR_SIZE) == probed)
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				what = 2;
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
776605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pgdp = pgd_offset_k(start);
778605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (what == 2) {
7797cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			*(pgd_t *)__nocache_fix(pgdp) = __pgd(probed);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start += SRMMU_PGDIR_SIZE;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7837d9fa4aa3d41e82d5d52612d07211ee243df3a20David S. Miller		if (pgd_none(*(pgd_t *)__nocache_fix(pgdp))) {
7847cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			pmdp = __srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE,
7857cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg						   SRMMU_PMD_TABLE_SIZE);
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (pmdp == NULL)
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				early_pgtable_allocfail("pmd");
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE);
789642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborg			pgd_set(__nocache_fix(pgdp), pmdp);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7919701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg		pmdp = pmd_offset(__nocache_fix(pgdp), start);
792605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
793f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg			ptep = __srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ptep == NULL)
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				early_pgtable_allocfail("pte");
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memset(__nocache_fix(ptep), 0, PTE_SIZE);
797642ea3ed9c652bb9e105e55afcb9ad15b040f71fSam Ravnborg			pmd_set(__nocache_fix(pmdp), ptep);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
799605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (what == 1) {
800605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg			/* We bend the rule where all 16 PTPs in a pmd_t point
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * inside the same PTE page, and we leak a perfectly
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * good hardware PTE piece. Alternatives seem worse.
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned int x;	/* Index of HW PMD in soft cluster */
8057cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			unsigned long *val;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			x = (start >> PMD_SHIFT) & 15;
8077cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			val = &pmdp->pmdv[x];
8087cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg			*(unsigned long *)__nocache_fix(val) = probed;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start += SRMMU_REAL_PMD_SIZE;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8129701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg		ptep = pte_offset_kernel(__nocache_fix(pmdp), start);
8137cdfbc74c8820cd33367fb3d61edcbe9829a06c5Sam Ravnborg		*(pte_t *)__nocache_fix(ptep) = __pte(probed);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start += PAGE_SIZE;
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define KERNEL_PTE(page_shifted) ((page_shifted)|SRMMU_CACHE|SRMMU_PRIV|SRMMU_VALID)
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Create a third-level SRMMU 16MB page mapping. */
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init do_large_mapping(unsigned long vaddr, unsigned long phys_base)
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgdp = pgd_offset_k(vaddr);
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long big_pte;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	big_pte = KERNEL_PTE(phys_base >> 4);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*(pgd_t *)__nocache_fix(pgdp) = __pgd(big_pte);
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE. */
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long pstart = (sp_banks[sp_entry].base_addr & SRMMU_PGDIR_MASK);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long vstart = (vbase & SRMMU_PGDIR_MASK);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long vend = SRMMU_PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes);
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Map "low" memory only */
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned long min_vaddr = PAGE_OFFSET;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned long max_vaddr = PAGE_OFFSET + SRMMU_MAXMEM;
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vstart < min_vaddr || vstart >= max_vaddr)
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return vstart;
842605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vend > max_vaddr || vend < min_vaddr)
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vend = max_vaddr;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
846605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	while (vstart < vend) {
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_large_mapping(vstart, pstart);
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vstart += SRMMU_PGDIR_SIZE; pstart += SRMMU_PGDIR_SIZE;
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return vstart;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
85332442467ed58ba7d32d02a27146650b9a4763b5dSam Ravnborgstatic void __init map_kernel(void)
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (phys_base > 0) {
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_large_mapping(PAGE_OFFSET, phys_base);
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		map_spbank((unsigned long)__va(sp_banks[i].base_addr), i);
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8662066aadd53c563445039d6490b685783816270ecPaul Gortmakervoid (*poke_srmmu)(void) = NULL;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init srmmu_paging_init(void)
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8708d1255627d4ce9cb4b9d0a1c44b6c18d92e84a99Andres Salomon	int i;
8718d1255627d4ce9cb4b9d0a1c44b6c18d92e84a99Andres Salomon	phandle cpunode;
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char node_str[128];
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd_t *pgd;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pmd_t *pmd;
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pte_t *pte;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long pages_avail;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
878b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	init_mm.context = (unsigned long) NO_CONTEXT;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sparc_iomap.start = SUN4M_IOBASE_VADDR;	/* 16MB of IOSPACE on all sun4m's. */
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sparc_cpu_model == sun4d)
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		num_contexts = 65536; /* We know it is Viking */
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Find the number of contexts on the srmmu. */
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpunode = prom_getchild(prom_root_node);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		num_contexts = 0;
887605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		while (cpunode != 0) {
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			prom_getstring(cpunode, "device_type", node_str, sizeof(node_str));
889605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg			if (!strcmp(node_str, "cpu")) {
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				num_contexts = prom_getintdefault(cpunode, "mmu-nctx", 0x8);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cpunode = prom_getsibling(cpunode);
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
897605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (!num_contexts) {
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("Something wrong, can't find cpu node in paging_init.\n");
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pages_avail = 0;
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	last_valid_pfn = bootmem_init(&pages_avail);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_nocache_calcsize();
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_nocache_init();
907f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	srmmu_inherit_prom_mappings(0xfe400000, (LINUX_OPPROM_ENDVM - PAGE_SIZE));
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	map_kernel();
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ctx table has to be physically aligned to its size */
911f71a2aacc63e3185e27ee45e8ebc2bebad9bec28Sam Ravnborg	srmmu_context_table = __srmmu_get_nocache(num_contexts * sizeof(ctxd_t), num_contexts * sizeof(ctxd_t));
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_ctx_table_phys = (ctxd_t *)__nocache_pa((unsigned long)srmmu_context_table);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
914605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	for (i = 0; i < num_contexts; i++)
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_ctxd_set((ctxd_t *)__nocache_fix(&srmmu_context_table[i]), srmmu_swapper_pg_dir);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_cache_all();
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys);
919a54123e27779049d27d21e6c8adfee73aa2c0734Bob Breuer#ifdef CONFIG_SMP
920a54123e27779049d27d21e6c8adfee73aa2c0734Bob Breuer	/* Stop from hanging here... */
9215d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	local_ops->tlb_all();
922a54123e27779049d27d21e6c8adfee73aa2c0734Bob Breuer#else
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_tlb_all();
924a54123e27779049d27d21e6c8adfee73aa2c0734Bob Breuer#endif
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poke_srmmu();
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END);
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_allocate_ptable_skeleton(
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__fix_to_virt(__end_of_fixed_addresses - 1), FIXADDR_TOP);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_END);
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pgd = pgd_offset_k(PKMAP_BASE);
9359701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg	pmd = pmd_offset(pgd, PKMAP_BASE);
9369701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborg	pte = pte_offset_kernel(pmd, PKMAP_BASE);
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pkmap_page_table = pte;
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_cache_all();
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_tlb_all();
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sparc_context_init(num_contexts);
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kmap_init();
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long zones_size[MAX_NR_ZONES];
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long zholes_size[MAX_NR_ZONES];
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long npages;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int znum;
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (znum = 0; znum < MAX_NR_ZONES; znum++)
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			zones_size[znum] = zholes_size[znum] = 0;
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		npages = max_low_pfn - pfn_base;
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		zones_size[ZONE_DMA] = npages;
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		zholes_size[ZONE_DMA] = npages - pages_avail;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		npages = highend_pfn - max_low_pfn;
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		zones_size[ZONE_HIGHMEM] = npages;
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9649109fb7b3520de187ebc3646c209d66a233f7169Johannes Weiner		free_area_init_node(0, zones_size, pfn_base, zholes_size);
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9689701b264d3267b55ace45bc579eabefc7decfa57Sam Ravnborgvoid mmu_info(struct seq_file *m)
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
970605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	seq_printf(m,
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   "MMU type\t: %s\n"
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   "contexts\t: %d\n"
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   "nocache total\t: %ld\n"
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   "nocache used\t: %d\n",
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   srmmu_name,
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   num_contexts,
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   srmmu_nocache_size,
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   srmmu_nocache_map.used << SRMMU_NOCACHE_BITMAP_SHIFT);
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborgint init_new_context(struct task_struct *tsk, struct mm_struct *mm)
982b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg{
983b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	mm->context = NO_CONTEXT;
984b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg	return 0;
985b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg}
986b585e8551b352cee95cf060b7eddc76d16e6120aSam Ravnborg
987b796c6da512c5c284c850e92c084725d5cecde63Sam Ravnborgvoid destroy_context(struct mm_struct *mm)
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
990605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (mm->context != NO_CONTEXT) {
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flush_cache_mm(mm);
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_ctxd_set(&srmmu_context_table[mm->context], srmmu_swapper_pg_dir);
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flush_tlb_mm(mm);
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock(&srmmu_context_spinlock);
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_context(mm->context);
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock(&srmmu_context_spinlock);
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mm->context = NO_CONTEXT;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Init various srmmu chip types. */
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init srmmu_is_bad(void)
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	prom_printf("Could not determine SRMMU chip type.\n");
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	prom_halt();
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init init_vac_layout(void)
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10108d1255627d4ce9cb4b9d0a1c44b6c18d92e84a99Andres Salomon	phandle nd;
10118d1255627d4ce9cb4b9d0a1c44b6c18d92e84a99Andres Salomon	int cache_lines;
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char node_str[128];
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cpu = 0;
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long max_size = 0;
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long min_line_size = 0x10000000;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	nd = prom_getchild(prom_root_node);
1020605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	while ((nd = prom_getsibling(nd)) != 0) {
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_getstring(nd, "device_type", node_str, sizeof(node_str));
1022605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (!strcmp(node_str, "cpu")) {
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vac_line_size = prom_getint(nd, "cache-line-size");
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (vac_line_size == -1) {
1025605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg				prom_printf("can't determine cache-line-size, halting.\n");
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				prom_halt();
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cache_lines = prom_getint(nd, "cache-nlines");
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cache_lines == -1) {
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				prom_printf("can't determine cache-nlines, halting.\n");
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				prom_halt();
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vac_cache_size = cache_lines * vac_line_size;
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
1036605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg			if (vac_cache_size > max_size)
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				max_size = vac_cache_size;
1038605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg			if (vac_line_size < min_line_size)
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				min_line_size = vac_line_size;
1040a54123e27779049d27d21e6c8adfee73aa2c0734Bob Breuer			//FIXME: cpus not contiguous!!
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cpu++;
1042ec7c14bde80a11e325f26b339b8570a929e87223Rusty Russell			if (cpu >= nr_cpu_ids || !cpu_online(cpu))
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1049605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (nd == 0) {
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("No CPU nodes found, halting.\n");
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vac_cache_size = max_size;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vac_line_size = min_line_size;
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("SRMMU: Using VAC size of %d bytes, line size %d bytes.\n",
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (int)vac_cache_size, (int)vac_line_size);
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10612066aadd53c563445039d6490b685783816270ecPaul Gortmakerstatic void poke_hypersparc(void)
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long clear;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mreg = srmmu_get_mmureg();
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hyper_flush_unconditional_combined();
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg &= ~(HYPERSPARC_CWENABLE);
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= (HYPERSPARC_CENABLE | HYPERSPARC_WBENABLE);
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= (HYPERSPARC_CMODE);
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_mmureg(mreg);
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 /* XXX I think this is bad news... -DaveM */
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hyper_clear_all_tags();
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	put_ross_icr(HYPERSPARC_ICCR_FTD | HYPERSPARC_ICCR_ICE);
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hyper_flush_whole_icache();
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear = srmmu_get_faddr();
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear = srmmu_get_fstatus();
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10845d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic const struct sparc32_cachetlb_ops hypersparc_ops = {
10855d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_all	= hypersparc_flush_cache_all,
10865d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_mm	= hypersparc_flush_cache_mm,
10875d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_page	= hypersparc_flush_cache_page,
10885d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_range	= hypersparc_flush_cache_range,
10895d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_all	= hypersparc_flush_tlb_all,
10905d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_mm		= hypersparc_flush_tlb_mm,
10915d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_page	= hypersparc_flush_tlb_page,
10925d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_range	= hypersparc_flush_tlb_range,
10935d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_to_ram	= hypersparc_flush_page_to_ram,
10945d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.sig_insns	= hypersparc_flush_sig_insns,
10955d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_for_dma	= hypersparc_flush_page_for_dma,
10965d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller};
10975d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init init_hypersparc(void)
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_name = "ROSS HyperSparc";
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_modtype = HyperSparc;
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_vac_layout();
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	is_hypersparc = 1;
11065d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	sparc32_cachetlb_ops = &hypersparc_ops;
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poke_srmmu = poke_hypersparc;
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hypersparc_setup_blockops();
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11132066aadd53c563445039d6490b685783816270ecPaul Gortmakerstatic void poke_swift(void)
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mreg;
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clear any crap from the cache or else... */
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	swift_flush_cache_all();
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable I & D caches */
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg = srmmu_get_mmureg();
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= (SWIFT_IE | SWIFT_DE);
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The Swift branch folding logic is completely broken.  At
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * trap time, if things are just right, if can mistakenly
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * think that a trap is coming from kernel mode when in fact
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * it is coming from user mode (it mis-executes the branch in
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the trap code).  So you see things like crashme completely
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * hosing your machine which is completely unacceptable.  Turn
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * this shit off... nice job Fujitsu.
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg &= ~(SWIFT_BF);
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_mmureg(mreg);
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11365d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic const struct sparc32_cachetlb_ops swift_ops = {
11375d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_all	= swift_flush_cache_all,
11385d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_mm	= swift_flush_cache_mm,
11395d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_page	= swift_flush_cache_page,
11405d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_range	= swift_flush_cache_range,
11415d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_all	= swift_flush_tlb_all,
11425d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_mm		= swift_flush_tlb_mm,
11435d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_page	= swift_flush_tlb_page,
11445d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_range	= swift_flush_tlb_range,
11455d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_to_ram	= swift_flush_page_to_ram,
11465d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.sig_insns	= swift_flush_sig_insns,
11475d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_for_dma	= swift_flush_page_for_dma,
11485d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller};
11495d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SWIFT_MASKID_ADDR  0x10003018
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init init_swift(void)
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long swift_rev;
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("lda [%1] %2, %0\n\t"
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "srl %0, 0x18, %0\n\t" :
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "=r" (swift_rev) :
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "r" (SWIFT_MASKID_ADDR), "i" (ASI_M_BYPASS));
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_name = "Fujitsu Swift";
1160605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	switch (swift_rev) {
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x11:
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x20:
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x23:
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x30:
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_modtype = Swift_lots_o_bugs;
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwbug_bitmask |= (HWBUG_KERN_ACCBROKEN | HWBUG_KERN_CBITBROKEN);
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Gee george, I wonder why Sun is so hush hush about
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * this hardware bug... really braindamage stuff going
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * on here.  However I think we can find a way to avoid
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * all of the workaround overhead under Linux.  Basically,
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * any page fault can cause kernel pages to become user
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * accessible (the mmu gets confused and clears some of
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the ACC bits in kernel ptes).  Aha, sounds pretty
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * horrible eh?  But wait, after extensive testing it appears
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * that if you use pgd_t level large kernel pte's (like the
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * 4MB pages on the Pentium) the bug does not get tripped
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * at all.  This avoids almost all of the major overhead.
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Welcome to a world where your vendor tells you to,
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * "apply this kernel patch" instead of "sorry for the
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * broken hardware, send it back and we'll give you
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * properly functioning parts"
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x25:
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x31:
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_modtype = Swift_bad_c;
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hwbug_bitmask |= HWBUG_KERN_CBITBROKEN;
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * You see Sun allude to this hardware bug but never
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * admit things directly, they'll say things like,
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * "the Swift chip cache problems" or similar.
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_modtype = Swift_ok;
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11986cb79b3f3ba2b14590cac02ee13ab7410b6225edJoe Perches	}
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12005d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	sparc32_cachetlb_ops = &swift_ops;
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_page_for_dma_global = 0;
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Are you now convinced that the Swift is one of the
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * biggest VLSI abortions of all time?  Bravo Fujitsu!
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Fujitsu, the !#?!%$'d up processor people.  I bet if
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * you examined the microcode of the Swift you'd find
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * XXX's all over the place.
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poke_srmmu = poke_swift;
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_cache_all(void)
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_user_windows();
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	turbosparc_idflash_clear();
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_cache_mm(struct mm_struct *mm)
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_BEGIN(mm)
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_user_windows();
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	turbosparc_idflash_clear();
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_END
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_BEGIN(vma->vm_mm)
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_user_windows();
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	turbosparc_idflash_clear();
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_END
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_BEGIN(vma->vm_mm)
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_user_windows();
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vma->vm_flags & VM_EXEC)
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		turbosparc_flush_icache();
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	turbosparc_flush_dcache();
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_END
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TurboSparc is copy-back, if we turn it on, but this does not work. */
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_page_to_ram(unsigned long page)
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef TURBOSPARC_WRITEBACK
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	volatile unsigned long clear;
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251805918f80fb11d95e9b117a6faf5a6a7a8339e49Sam Ravnborg	if (srmmu_probe(page))
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		turbosparc_flush_page_cache(page);
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear = srmmu_get_fstatus();
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_page_for_dma(unsigned long page)
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	turbosparc_flush_dcache();
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_tlb_all(void)
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_flush_whole_tlb();
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_tlb_mm(struct mm_struct *mm)
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_BEGIN(mm)
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_flush_whole_tlb();
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_END
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_BEGIN(vma->vm_mm)
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_flush_whole_tlb();
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_END
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void turbosparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_BEGIN(vma->vm_mm)
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_flush_whole_tlb();
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FLUSH_END
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12932066aadd53c563445039d6490b685783816270ecPaul Gortmakerstatic void poke_turbosparc(void)
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mreg = srmmu_get_mmureg();
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long ccreg;
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clear any crap from the cache or else... */
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	turbosparc_flush_cache_all();
1300605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	/* Temporarily disable I & D caches */
1301605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	mreg &= ~(TURBOSPARC_ICENABLE | TURBOSPARC_DCENABLE);
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg &= ~(TURBOSPARC_PCENABLE);		/* Don't check parity */
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_mmureg(mreg);
1304605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccreg = turbosparc_get_ccreg();
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef TURBOSPARC_WRITEBACK
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccreg |= (TURBOSPARC_SNENABLE);		/* Do DVMA snooping in Dcache */
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccreg &= ~(TURBOSPARC_uS2 | TURBOSPARC_WTENABLE);
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Write-back D-cache, emulate VLSI
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * abortion number three, not number one */
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* For now let's play safe, optimize later */
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccreg |= (TURBOSPARC_SNENABLE | TURBOSPARC_WTENABLE);
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Do DVMA snooping in Dcache, Write-thru D-cache */
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ccreg &= ~(TURBOSPARC_uS2);
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Emulate VLSI abortion number three, not number one */
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ccreg & 7) {
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0: /* No SE cache */
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 7: /* Test mode */
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ccreg |= (TURBOSPARC_SCENABLE);
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1327605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	turbosparc_set_ccreg(ccreg);
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= (TURBOSPARC_ICENABLE | TURBOSPARC_DCENABLE); /* I & D caches on */
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= (TURBOSPARC_ICSNOOP);		/* Icache snooping on */
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_mmureg(mreg);
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13345d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic const struct sparc32_cachetlb_ops turbosparc_ops = {
13355d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_all	= turbosparc_flush_cache_all,
13365d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_mm	= turbosparc_flush_cache_mm,
13375d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_page	= turbosparc_flush_cache_page,
13385d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_range	= turbosparc_flush_cache_range,
13395d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_all	= turbosparc_flush_tlb_all,
13405d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_mm		= turbosparc_flush_tlb_mm,
13415d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_page	= turbosparc_flush_tlb_page,
13425d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_range	= turbosparc_flush_tlb_range,
13435d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_to_ram	= turbosparc_flush_page_to_ram,
13445d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.sig_insns	= turbosparc_flush_sig_insns,
13455d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_for_dma	= turbosparc_flush_page_for_dma,
13465d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller};
13475d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init init_turbosparc(void)
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_name = "Fujitsu TurboSparc";
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_modtype = TurboSparc;
13525d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	sparc32_cachetlb_ops = &turbosparc_ops;
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poke_srmmu = poke_turbosparc;
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13562066aadd53c563445039d6490b685783816270ecPaul Gortmakerstatic void poke_tsunami(void)
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mreg = srmmu_get_mmureg();
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tsunami_flush_icache();
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tsunami_flush_dcache();
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg &= ~TSUNAMI_ITD;
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= (TSUNAMI_IENAB | TSUNAMI_DENAB);
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_mmureg(mreg);
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13675d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic const struct sparc32_cachetlb_ops tsunami_ops = {
13685d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_all	= tsunami_flush_cache_all,
13695d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_mm	= tsunami_flush_cache_mm,
13705d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_page	= tsunami_flush_cache_page,
13715d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_range	= tsunami_flush_cache_range,
13725d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_all	= tsunami_flush_tlb_all,
13735d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_mm		= tsunami_flush_tlb_mm,
13745d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_page	= tsunami_flush_tlb_page,
13755d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_range	= tsunami_flush_tlb_range,
13765d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_to_ram	= tsunami_flush_page_to_ram,
13775d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.sig_insns	= tsunami_flush_sig_insns,
13785d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_for_dma	= tsunami_flush_page_for_dma,
13795d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller};
13805d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init init_tsunami(void)
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Tsunami's pretty sane, Sun and TI actually got it
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * somewhat right this time.  Fujitsu should have
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * taken some lessons from them.
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_name = "TI Tsunami";
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_modtype = Tsunami;
13915d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	sparc32_cachetlb_ops = &tsunami_ops;
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poke_srmmu = poke_tsunami;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tsunami_setup_blockops();
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13972066aadd53c563445039d6490b685783816270ecPaul Gortmakerstatic void poke_viking(void)
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mreg = srmmu_get_mmureg();
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int smp_catch;
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14025d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (viking_mxcc_present) {
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long mxcc_control = mxcc_get_creg();
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mxcc_control |= (MXCC_CTL_ECE | MXCC_CTL_PRE | MXCC_CTL_MCE);
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mxcc_control &= ~(MXCC_CTL_RRC);
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mxcc_set_creg(mxcc_control);
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We don't need memory parity checks.
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * XXX This is a mess, have to dig out later. ecd.
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		viking_mxcc_turn_off_parity(&mreg, &mxcc_control);
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We do cache ptables on MXCC. */
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mreg |= VIKING_TCENABLE;
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long bpreg;
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mreg &= ~(VIKING_TCENABLE);
1421605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		if (smp_catch++) {
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Must disable mixed-cmd mode here for other cpu's. */
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bpreg = viking_get_bpreg();
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bpreg &= ~(VIKING_ACTION_MIX);
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			viking_set_bpreg(bpreg);
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Just in case PROM does something funny. */
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msi_set_sync();
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= VIKING_SPENABLE;
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= (VIKING_ICENABLE | VIKING_DCENABLE);
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg |= VIKING_SBENABLE;
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg &= ~(VIKING_ACENABLE);
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_set_mmureg(mreg);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14395d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic struct sparc32_cachetlb_ops viking_ops = {
14405d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_all	= viking_flush_cache_all,
14415d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_mm	= viking_flush_cache_mm,
14425d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_page	= viking_flush_cache_page,
14435d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_range	= viking_flush_cache_range,
14445d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_all	= viking_flush_tlb_all,
14455d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_mm		= viking_flush_tlb_mm,
14465d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_page	= viking_flush_tlb_page,
14475d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_range	= viking_flush_tlb_range,
14485d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_to_ram	= viking_flush_page_to_ram,
14495d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.sig_insns	= viking_flush_sig_insns,
14505d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_for_dma	= viking_flush_page_for_dma,
14515d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller};
14525d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
14535d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller#ifdef CONFIG_SMP
14545d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller/* On sun4d the cpu broadcasts local TLB flushes, so we can just
14555d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * perform the local TLB flush and all the other cpus will see it.
14565d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * But, unfortunately, there is a bug in the sun4d XBUS backplane
14575d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * that requires that we add some synchronization to these flushes.
14585d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller *
14595d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * The bug is that the fifo which keeps track of all the pending TLB
14605d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * broadcasts in the system is an entry or two too small, so if we
14615d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * have too many going at once we'll overflow that fifo and lose a TLB
14625d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * flush resulting in corruption.
14635d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller *
14645d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * Our workaround is to take a global spinlock around the TLB flushes,
14655d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * which guarentees we won't ever have too many pending.  It's a big
14665d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * hammer, but a semaphore like system to make sure we only have N TLB
14675d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * flushes going at once will require SMP locking anyways so there's
14685d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller * no real value in trying any harder than this.
14695d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller */
14705d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic struct sparc32_cachetlb_ops viking_sun4d_smp_ops = {
14715d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_all	= viking_flush_cache_all,
14725d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_mm	= viking_flush_cache_mm,
14735d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_page	= viking_flush_cache_page,
14745d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_range	= viking_flush_cache_range,
14755d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_all	= sun4dsmp_flush_tlb_all,
14765d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_mm		= sun4dsmp_flush_tlb_mm,
14775d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_page	= sun4dsmp_flush_tlb_page,
14785d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_range	= sun4dsmp_flush_tlb_range,
14795d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_to_ram	= viking_flush_page_to_ram,
14805d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.sig_insns	= viking_flush_sig_insns,
14815d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_for_dma	= viking_flush_page_for_dma,
14825d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller};
14835d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller#endif
14845d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init init_viking(void)
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mreg = srmmu_get_mmureg();
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Ahhh, the viking.  SRMMU VLSI abortion number two... */
1490605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (mreg & VIKING_MMODE) {
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_name = "TI Viking";
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		viking_mxcc_present = 0;
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msi_set_sync();
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We need this to make sure old viking takes no hits
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * on it's cache for dma snoops to workaround the
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * "load from non-cacheable memory" interrupt bug.
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * This is only necessary because of the new way in
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * which we use the IOMMU.
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
15025d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		viking_ops.page_for_dma = viking_flush_page;
15035d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller#ifdef CONFIG_SMP
15045d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		viking_sun4d_smp_ops.page_for_dma = viking_flush_page;
15055d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller#endif
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flush_page_for_dma_global = 0;
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_name = "TI Viking/MXCC";
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		viking_mxcc_present = 1;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		srmmu_cache_pagetables = 1;
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15135d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
15145d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		&viking_ops;
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
15165d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (sparc_cpu_model == sun4d)
15175d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
15185d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			&viking_sun4d_smp_ops;
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poke_srmmu = poke_viking;
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Probe for the srmmu chip version. */
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init get_srmmu_type(void)
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mreg, psr;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mod_typ, mod_rev, psr_typ, psr_vers;
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_modtype = SRMMU_INVAL_MOD;
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hwbug_bitmask = 0;
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mreg = srmmu_get_mmureg(); psr = get_psr();
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mod_typ = (mreg & 0xf0000000) >> 28;
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mod_rev = (mreg & 0x0f000000) >> 24;
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	psr_typ = (psr >> 28) & 0xf;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	psr_vers = (psr >> 24) & 0xf;
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
153975d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele	/* First, check for sparc-leon. */
154075d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele	if (sparc_cpu_model == sparc_leon) {
154175d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele		init_leon();
154275d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele		return;
154375d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele	}
154475d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele
154575d9e34698540e96b422293e1d76ab02cc7faefbKonrad Eisele	/* Second, check for HyperSparc or Cypress. */
1546605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (mod_typ == 1) {
1547605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		switch (mod_rev) {
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 7:
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* UP or MP Hypersparc */
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			init_hypersparc();
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0:
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 2:
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 10:
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 11:
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 12:
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 13:
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 14:
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 15:
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
1561c7020eb4661eaf568a277056258a387ef88a9349David S. Miller			prom_printf("Sparc-Linux Cypress support does not longer exit.\n");
1562c7020eb4661eaf568a277056258a387ef88a9349David S. Miller			prom_halt();
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
15646cb79b3f3ba2b14590cac02ee13ab7410b6225edJoe Perches		}
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1567605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
1568605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	/* Now Fujitsu TurboSparc. It might happen that it is
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * in Swift emulation mode, so we will check later...
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (psr_typ == 0 && psr_vers == 5) {
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_turbosparc();
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Next check for Fujitsu Swift. */
1577605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (psr_typ == 0 && psr_vers == 4) {
15788d1255627d4ce9cb4b9d0a1c44b6c18d92e84a99Andres Salomon		phandle cpunode;
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		char node_str[128];
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Look if it is not a TurboSparc emulating Swift... */
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpunode = prom_getchild(prom_root_node);
1583605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg		while ((cpunode = prom_getsibling(cpunode)) != 0) {
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			prom_getstring(cpunode, "device_type", node_str, sizeof(node_str));
1585605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg			if (!strcmp(node_str, "cpu")) {
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!prom_getintdefault(cpunode, "psr-implementation", 1) &&
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    prom_getintdefault(cpunode, "psr-version", 1) == 5) {
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					init_turbosparc();
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return;
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1594605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_swift();
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now the Viking family of srmmu. */
1600605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (psr_typ == 4 &&
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   ((psr_vers == 0) ||
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ((psr_vers == 1) && (mod_typ == 0) && (mod_rev == 0)))) {
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_viking();
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Finally the Tsunami. */
1608605ae96240a165baaceeff0eeec35e41d68dc978Sam Ravnborg	if (psr_typ == 4 && psr_vers == 1 && (mod_typ || mod_rev)) {
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		init_tsunami();
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Oh well */
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srmmu_is_bad();
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Local cross-calls. */
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void smp_flush_page_for_dma(unsigned long page)
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16215d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	xc1((smpfunc_t) local_ops->page_for_dma, page);
16225d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	local_ops->page_for_dma(page);
16235d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
16245d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16255d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_cache_all(void)
16265d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
16275d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	xc0((smpfunc_t) local_ops->cache_all);
16285d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	local_ops->cache_all();
16295d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
16305d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16315d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_tlb_all(void)
16325d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
16335d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	xc0((smpfunc_t) local_ops->tlb_all);
16345d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	local_ops->tlb_all();
16355d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
16365d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16375d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_cache_mm(struct mm_struct *mm)
16385d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
16395d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (mm->context != NO_CONTEXT) {
16405d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_t cpu_mask;
16415d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_copy(&cpu_mask, mm_cpumask(mm));
16425d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
16435d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		if (!cpumask_empty(&cpu_mask))
16445d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			xc1((smpfunc_t) local_ops->cache_mm, (unsigned long) mm);
16455d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		local_ops->cache_mm(mm);
16465d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	}
16475d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
16485d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16495d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_tlb_mm(struct mm_struct *mm)
16505d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
16515d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (mm->context != NO_CONTEXT) {
16525d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_t cpu_mask;
16535d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_copy(&cpu_mask, mm_cpumask(mm));
16545d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
16555d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		if (!cpumask_empty(&cpu_mask)) {
16565d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			xc1((smpfunc_t) local_ops->tlb_mm, (unsigned long) mm);
16575d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			if (atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
16585d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller				cpumask_copy(mm_cpumask(mm),
16595d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller					     cpumask_of(smp_processor_id()));
16605d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		}
16615d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		local_ops->tlb_mm(mm);
16625d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	}
16635d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
16645d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16655d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_cache_range(struct vm_area_struct *vma,
16665d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller				  unsigned long start,
16675d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller				  unsigned long end)
16685d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
16695d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	struct mm_struct *mm = vma->vm_mm;
16705d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16715d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (mm->context != NO_CONTEXT) {
16725d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_t cpu_mask;
16735d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_copy(&cpu_mask, mm_cpumask(mm));
16745d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
16755d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		if (!cpumask_empty(&cpu_mask))
16765d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			xc3((smpfunc_t) local_ops->cache_range,
16775d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			    (unsigned long) vma, start, end);
16785d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		local_ops->cache_range(vma, start, end);
16795d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	}
16805d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
16815d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16825d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_tlb_range(struct vm_area_struct *vma,
16835d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller				unsigned long start,
16845d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller				unsigned long end)
16855d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
16865d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	struct mm_struct *mm = vma->vm_mm;
16875d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
16885d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (mm->context != NO_CONTEXT) {
16895d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_t cpu_mask;
16905d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_copy(&cpu_mask, mm_cpumask(mm));
16915d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
16925d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		if (!cpumask_empty(&cpu_mask))
16935d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			xc3((smpfunc_t) local_ops->tlb_range,
16945d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			    (unsigned long) vma, start, end);
16955d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		local_ops->tlb_range(vma, start, end);
16965d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	}
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16995d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
17005d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
17015d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	struct mm_struct *mm = vma->vm_mm;
17025d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17035d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (mm->context != NO_CONTEXT) {
17045d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_t cpu_mask;
17055d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_copy(&cpu_mask, mm_cpumask(mm));
17065d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
17075d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		if (!cpumask_empty(&cpu_mask))
17085d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			xc2((smpfunc_t) local_ops->cache_page,
17095d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			    (unsigned long) vma, page);
17105d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		local_ops->cache_page(vma, page);
17115d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	}
17125d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
17135d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17145d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
17155d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
17165d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	struct mm_struct *mm = vma->vm_mm;
17175d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17185d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (mm->context != NO_CONTEXT) {
17195d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_t cpu_mask;
17205d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_copy(&cpu_mask, mm_cpumask(mm));
17215d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
17225d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		if (!cpumask_empty(&cpu_mask))
17235d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			xc2((smpfunc_t) local_ops->tlb_page,
17245d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller			    (unsigned long) vma, page);
17255d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		local_ops->tlb_page(vma, page);
17265d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	}
17275d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
17285d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17295d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_page_to_ram(unsigned long page)
17305d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
17315d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	/* Current theory is that those who call this are the one's
17325d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	 * who have just dirtied their cache with the pages contents
17335d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	 * in kernel space, therefore we only run this on local cpu.
17345d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	 *
17355d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	 * XXX This experiment failed, research further... -DaveM
17365d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	 */
17375d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller#if 1
17385d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	xc1((smpfunc_t) local_ops->page_to_ram, page);
17395d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller#endif
17405d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	local_ops->page_to_ram(page);
17415d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
17425d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17435d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
17445d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller{
17455d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	cpumask_t cpu_mask;
17465d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	cpumask_copy(&cpu_mask, mm_cpumask(mm));
17475d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
17485d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (!cpumask_empty(&cpu_mask))
17495d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		xc2((smpfunc_t) local_ops->sig_insns,
17505d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		    (unsigned long) mm, insn_addr);
17515d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	local_ops->sig_insns(mm, insn_addr);
17525d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller}
17535d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17545d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Millerstatic struct sparc32_cachetlb_ops smp_cachetlb_ops = {
17555d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_all	= smp_flush_cache_all,
17565d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_mm	= smp_flush_cache_mm,
17575d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_page	= smp_flush_cache_page,
17585d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.cache_range	= smp_flush_cache_range,
17595d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_all	= smp_flush_tlb_all,
17605d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_mm		= smp_flush_tlb_mm,
17615d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_page	= smp_flush_tlb_page,
17625d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.tlb_range	= smp_flush_tlb_range,
17635d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_to_ram	= smp_flush_page_to_ram,
17645d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.sig_insns	= smp_flush_sig_insns,
17655d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	.page_for_dma	= smp_flush_page_for_dma,
17665d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller};
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Load up routines and constants for sun4m and sun4d mmu */
1770a3c5c6637bd7ddae34aa0cd8b6baf7cc33a8b163Sam Ravnborgvoid __init load_mmu(void)
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Functions */
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	get_srmmu_type();
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* El switcheroo... */
17775d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	local_ops = sparc32_cachetlb_ops;
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17795d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	if (sparc_cpu_model == sun4d || sparc_cpu_model == sparc_leon) {
17805d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.tlb_all = local_ops->tlb_all;
17815d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.tlb_mm = local_ops->tlb_mm;
17825d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.tlb_range = local_ops->tlb_range;
17835d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.tlb_page = local_ops->tlb_page;
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
178564273d08dfb41549df3cd815baaaff781cd99992David S. Miller
178664273d08dfb41549df3cd815baaaff781cd99992David S. Miller	if (poke_srmmu == poke_viking) {
178764273d08dfb41549df3cd815baaaff781cd99992David S. Miller		/* Avoid unnecessary cross calls. */
17885d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.cache_all = local_ops->cache_all;
17895d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.cache_mm = local_ops->cache_mm;
17905d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.cache_range = local_ops->cache_range;
17915d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.cache_page = local_ops->cache_page;
17925d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17935d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.page_to_ram = local_ops->page_to_ram;
17945d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.sig_insns = local_ops->sig_insns;
17955d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		smp_cachetlb_ops.page_for_dma = local_ops->page_for_dma;
179664273d08dfb41549df3cd815baaaff781cd99992David S. Miller	}
17975d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller
17985d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	/* It really is const after this point. */
17995d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller	sparc32_cachetlb_ops = (const struct sparc32_cachetlb_ops *)
18005d83d66635bb1642f3c6a3690c28ff4afdf1ae5fDavid S. Miller		&smp_cachetlb_ops;
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sparc_cpu_model == sun4d)
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ld_mmu_iounit();
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ld_mmu_iommu();
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sparc_cpu_model == sun4d)
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sun4d_init_smp();
18108401707ff645521e9f21cbb8fe3b138f60e85680Konrad Eisele	else if (sparc_cpu_model == sparc_leon)
18118401707ff645521e9f21cbb8fe3b138f60e85680Konrad Eisele		leon_init_smp();
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sun4m_init_smp();
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1816