duke@435: /* trims@2708: * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_RUNTIME_ICACHE_HPP stefank@2314: #define SHARE_VM_RUNTIME_ICACHE_HPP stefank@2314: stefank@2314: #include "memory/allocation.hpp" stefank@2314: #include "runtime/stubCodeGenerator.hpp" stefank@2314: duke@435: // Interface for updating the instruction cache. Whenever the VM modifies duke@435: // code, part of the processor instruction cache potentially has to be flushed. duke@435: duke@435: // Default implementation is in icache.cpp, and can be hidden per-platform. duke@435: // Most platforms must provide only ICacheStubGenerator::generate_icache_flush(). duke@435: // Platforms that don't require icache flushing can just nullify the public duke@435: // members of AbstractICache in their ICache class. AbstractICache should never duke@435: // be referenced other than by deriving the ICache class from it. duke@435: // duke@435: // The code for the ICache class and for generate_icache_flush() must be in duke@435: // architecture-specific files, i.e., icache_.hpp/.cpp duke@435: duke@435: class AbstractICache : AllStatic { duke@435: public: duke@435: // The flush stub signature duke@435: typedef int (*flush_icache_stub_t)(address addr, int lines, int magic); duke@435: duke@435: protected: duke@435: // The flush stub function address duke@435: static flush_icache_stub_t _flush_icache_stub; duke@435: duke@435: // Call the flush stub duke@435: static void call_flush_stub(address start, int lines); duke@435: duke@435: public: duke@435: enum { duke@435: stub_size = 0, // Size of the icache flush stub in bytes duke@435: line_size = 0, // Icache line size in bytes duke@435: log2_line_size = 0 // log2(line_size) duke@435: }; duke@435: duke@435: static void initialize(); duke@435: static void invalidate_word(address addr); duke@435: static void invalidate_range(address start, int nbytes); duke@435: }; duke@435: duke@435: duke@435: // Must be included before the definition of ICacheStubGenerator duke@435: // because ICacheStubGenerator uses ICache definitions. duke@435: stefank@2314: #ifdef TARGET_ARCH_x86 stefank@2314: # include "icache_x86.hpp" stefank@2314: #endif stefank@2314: #ifdef TARGET_ARCH_sparc stefank@2314: # include "icache_sparc.hpp" stefank@2314: #endif stefank@2314: #ifdef TARGET_ARCH_zero stefank@2314: # include "icache_zero.hpp" stefank@2314: #endif bobv@2508: #ifdef TARGET_ARCH_arm bobv@2508: # include "icache_arm.hpp" bobv@2508: #endif bobv@2508: #ifdef TARGET_ARCH_ppc bobv@2508: # include "icache_ppc.hpp" bobv@2508: #endif stefank@2314: duke@435: duke@435: duke@435: class ICacheStubGenerator : public StubCodeGenerator { duke@435: public: duke@435: ICacheStubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {} duke@435: duke@435: // Generate the icache flush stub. duke@435: // duke@435: // Since we cannot flush the cache when this stub is generated, duke@435: // it must be generated first, and just to be sure, we do extra duke@435: // work to allow a check that these instructions got executed. duke@435: // duke@435: // The flush stub has three parameters (see flush_icache_stub_t). duke@435: // duke@435: // addr - Start address, must be aligned at log2_line_size duke@435: // lines - Number of line_size icache lines to flush duke@435: // magic - Magic number copied to result register to make sure duke@435: // the stub executed properly duke@435: // duke@435: // A template for generate_icache_flush is duke@435: // duke@435: // #define __ _masm-> duke@435: // duke@435: // void ICacheStubGenerator::generate_icache_flush( duke@435: // ICache::flush_icache_stub_t* flush_icache_stub duke@435: // ) { duke@435: // StubCodeMark mark(this, "ICache", "flush_icache_stub"); duke@435: // duke@435: // address start = __ pc(); duke@435: // duke@435: // // emit flush stub asm code duke@435: // duke@435: // // Must be set here so StubCodeMark destructor can call the flush stub. duke@435: // *flush_icache_stub = (ICache::flush_icache_stub_t)start; duke@435: // }; duke@435: // duke@435: // #undef __ duke@435: // duke@435: // The first use of flush_icache_stub must apply it to itself. The duke@435: // StubCodeMark destructor in generate_icache_flush will call Assembler::flush, duke@435: // which in turn will call invalidate_range (see asm/assembler.cpp), which duke@435: // in turn will call the flush stub *before* generate_icache_flush returns. duke@435: // The usual method of having generate_icache_flush return the address of the duke@435: // stub to its caller, which would then, e.g., store that address in duke@435: // flush_icache_stub, won't work. generate_icache_flush must itself set duke@435: // flush_icache_stub to the address of the stub it generates before duke@435: // the StubCodeMark destructor is invoked. duke@435: duke@435: void generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub); duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_RUNTIME_ICACHE_HPP