18be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi/* SMP global caching code 28be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * 38be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. 48be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * Written by David Howells (dhowells@redhat.com) 58be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * 68be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * This program is free software; you can redistribute it and/or 78be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * modify it under the terms of the GNU General Public Licence 88be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * as published by the Free Software Foundation; either version 98be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * 2 of the Licence, or (at your option) any later version. 108be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi */ 118be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <linux/module.h> 128be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <linux/mm.h> 138be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <linux/mman.h> 148be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <linux/threads.h> 158be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <linux/interrupt.h> 168be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <asm/page.h> 178be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <asm/pgtable.h> 188be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <asm/processor.h> 198be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <asm/cacheflush.h> 208be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <asm/io.h> 218be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <asm/uaccess.h> 228be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include <asm/smp.h> 238be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi#include "cache-smp.h" 248be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 258be062892365b09f41d64cda7fa63d306e95e0c9Akira TakeuchiDEFINE_SPINLOCK(smp_cache_lock); 268be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchistatic unsigned long smp_cache_mask; 278be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchistatic unsigned long smp_cache_start; 288be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchistatic unsigned long smp_cache_end; 298be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchistatic cpumask_t smp_cache_ipi_map; /* Bitmask of cache IPI done CPUs */ 308be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 318be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi/** 328be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * smp_cache_interrupt - Handle IPI request to flush caches. 338be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * 348be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * Handle a request delivered by IPI to flush the current CPU's 358be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * caches. The parameters are stored in smp_cache_*. 368be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi */ 378be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchivoid smp_cache_interrupt(void) 388be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi{ 398be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi unsigned long opr_mask = smp_cache_mask; 408be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 418be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi switch ((enum smp_dcache_ops)(opr_mask & SMP_DCACHE_OP_MASK)) { 428be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_DCACHE_NOP: 438be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 448be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_DCACHE_INV: 458be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_dcache_inv(); 468be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 478be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_DCACHE_INV_RANGE: 488be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_dcache_inv_range(smp_cache_start, smp_cache_end); 498be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 508be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_DCACHE_FLUSH: 518be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_dcache_flush(); 528be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 538be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_DCACHE_FLUSH_RANGE: 548be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_dcache_flush_range(smp_cache_start, 558be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi smp_cache_end); 568be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 578be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_DCACHE_FLUSH_INV: 588be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_dcache_flush_inv(); 598be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 608be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_DCACHE_FLUSH_INV_RANGE: 618be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_dcache_flush_inv_range(smp_cache_start, 628be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi smp_cache_end); 638be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 648be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi } 658be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 668be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi switch ((enum smp_icache_ops)(opr_mask & SMP_ICACHE_OP_MASK)) { 678be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_ICACHE_NOP: 688be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 698be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_ICACHE_INV: 708be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_icache_inv(); 718be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 728be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi case SMP_ICACHE_INV_RANGE: 738be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mn10300_local_icache_inv_range(smp_cache_start, smp_cache_end); 748be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi break; 758be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi } 768be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 778ea9716fd6aa761482caa5d4d64b256ed07ac09fKOSAKI Motohiro cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map); 788be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi} 798be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 808be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi/** 818be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * smp_cache_call - Issue an IPI to request the other CPUs flush caches 828be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * @opr_mask: Cache operation flags 838be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * @start: Start address of request 848be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * @end: End address of request 858be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * 868be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * Send cache flush IPI to other CPUs. This invokes smp_cache_interrupt() 878be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * above on those other CPUs and then waits for them to finish. 888be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * 898be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi * The caller must hold smp_cache_lock. 908be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi */ 918be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchivoid smp_cache_call(unsigned long opr_mask, 928be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi unsigned long start, unsigned long end) 938be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi{ 948be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi smp_cache_mask = opr_mask; 958be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi smp_cache_start = start; 968be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi smp_cache_end = end; 978ea9716fd6aa761482caa5d4d64b256ed07ac09fKOSAKI Motohiro cpumask_copy(&smp_cache_ipi_map, cpu_online_mask); 988ea9716fd6aa761482caa5d4d64b256ed07ac09fKOSAKI Motohiro cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map); 998be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 1008be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi send_IPI_allbutself(FLUSH_CACHE_IPI); 1018be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi 1028ea9716fd6aa761482caa5d4d64b256ed07ac09fKOSAKI Motohiro while (!cpumask_empty(&smp_cache_ipi_map)) 1038be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi /* nothing. lockup detection does not belong here */ 1048be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi mb(); 1058be062892365b09f41d64cda7fa63d306e95e0c9Akira Takeuchi} 106