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