/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.vm; import java.nio.ByteOrder; import org.jnode.annotation.Internal; import org.jnode.annotation.KernelSpace; import org.jnode.annotation.MagicPermission; import org.jnode.permission.JNodePermission; import org.jnode.system.resource.ResourceManager; import org.jnode.vm.classmgr.VmIsolatedStatics; import org.jnode.vm.classmgr.VmSharedStatics; import org.jnode.vm.compiler.IMTCompiler; import org.jnode.vm.compiler.NativeCodeCompiler; import org.jnode.vm.facade.MemoryMapEntry; import org.jnode.vm.facade.TypeSizeInfo; import org.jnode.vm.facade.VmUtils; import org.jnode.vm.objects.VmSystemObject; import org.jnode.vm.scheduler.IRQManager; import org.jnode.vm.scheduler.VmProcessor; import org.jnode.vm.scheduler.VmScheduler; import org.vmmagic.pragma.UninterruptiblePragma; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.Extent; import org.vmmagic.unboxed.Word; /** * Class describing a specific system architecture. * * @author Ewout Prangsma (epr@users.sourceforge.net) */ @MagicPermission public abstract class BaseVmArchitecture extends VmSystemObject implements org.jnode.vm.facade.VmArchitecture { private final JNodePermission MMAP_PERM = new JNodePermission("getMemoryMap"); private transient MemoryMapEntry[] memoryMap; private transient VmMultiMediaSupport multiMediaSupport; private final int referenceSize; private final VmStackReader stackReader; protected BaseVmArchitecture(int referenceSize, VmStackReader stackReader) { this.referenceSize = referenceSize; this.stackReader = stackReader; } /** * {@inheritDoc} */ public abstract String getName(); /** * Gets the full name of this architecture, including operating mode. * * @return the architecture's full name */ public abstract String getFullName(); /** * {@inheritDoc} */ public abstract ByteOrder getByteOrder(); /** * {@inheritDoc} */ @KernelSpace public final int getReferenceSize() { return referenceSize; } /** * {@inheritDoc} */ public abstract byte getLogPageSize(int region) throws UninterruptiblePragma; /** * Gets the size in bytes of an OS page in a given region * * @param region a {@link VirtualMemoryRegion} value * @return the page size */ public final Extent getPageSize(int region) throws UninterruptiblePragma { return Extent.fromIntZeroExtend(1 << getLogPageSize(region)); } /** * {@inheritDoc} */ public abstract TypeSizeInfo getTypeSizeInfo(); /** * Gets the stackreader for this architecture. * * @return the architecture's stack reader */ @KernelSpace public final VmStackReader getStackReader() { return stackReader; } /** * Gets all compilers for this architecture. * * @return The architecture's compilers, sorted by optimization level, from * least optimizing to most optimizing. */ public abstract NativeCodeCompiler[] getCompilers(); /** * Gets all test compilers for this architecture. * This can be used to test new compilers in a running system. * * @return The architecture's test compilers, sorted by optimization level, from * least optimizing to most optimizing. If there are no configured test compilers, * {@code null} will be returned. */ public abstract NativeCodeCompiler[] getTestCompilers(); /** * Gets the compiler of IMT's. * * @return the IMT compiler */ public abstract IMTCompiler getIMTCompiler(); /** * Called early on in the boot process (before the initialization of * the memory manager) to initialize any architecture specific variables. * Do not allocate memory here. * * @param emptyMmap If true, all page mappings in the AVAILABLE region * are removed. */ protected abstract void boot(boolean emptyMmap); /** * Find and start all processors in the system. * All all discovered processors to the given list. * The bootstrap processor is already on the given list. */ protected abstract void initializeProcessors(ResourceManager rm); /** * Call this method to register a processor found in {@link #initializeProcessors(ResourceManager)}. * * @param cpu */ protected final void addProcessor(VmProcessor cpu) { ((VmImpl) VmUtils.getVm()).addProcessor(cpu); } /** * Create a processor instance for this architecture. * * @return The processor */ protected abstract VmProcessor createProcessor(int id, VmSharedStatics sharedStatics, VmIsolatedStatics isolatedStatics, VmScheduler scheduler); /** * Create the IRQ manager for this architecture. * * @return the IRQManager */ @Internal public abstract IRQManager createIRQManager(VmProcessor processor); /** * {@inheritDoc} */ public Address getStart(int space) { switch (space) { case VirtualMemoryRegion.BOOTIMAGE: return Unsafe.getKernelStart(); case VirtualMemoryRegion.INITJAR: return Unsafe.getInitJarStart(); default: throw new IllegalArgumentException("Unknown space " + space); } } /** * {@inheritDoc} */ public Address getEnd(int space) { switch (space) { case VirtualMemoryRegion.BOOTIMAGE: return Unsafe.getBootHeapEnd(); case VirtualMemoryRegion.INITJAR: return Unsafe.getInitJarEnd(); default: throw new IllegalArgumentException("Unknown space " + space); } } /** * Gets the physical address of the first whole page available for use * by the memory manager. * * @return a physical address aligned on the appropriate page boundary */ protected final Word getFirstAvailableHeapPage() { return pageAlign(VirtualMemoryRegion.HEAP, Unsafe.getMemoryStart().toWord(), true); } /** * Page align a given address (represented as a Word) in a given region. * * @param v an address value * @param region a {@link VirtualMemoryRegion}. * @param up If true, the value will be rounded up, otherwise rounded down. * @return the corresponding page aligned address represented as a Word. */ public final Word pageAlign(int region, Word v, boolean up) { final int logPageSize = getLogPageSize(region); if (up) { v = v.add((1 << logPageSize) - 1); } return v.rshl(logPageSize).lsh(logPageSize); } /** * {@inheritDoc} */ public final Address pageAlign(int region, Address v, boolean up) { return pageAlign(region, v.toWord(), up).toAddress(); } /** * {@inheritDoc} */ public abstract boolean mmap(int region, Address start, Extent size, Address physAddr) throws UninterruptiblePragma; /** * Unmap a region of the virtual memory space. Note that you cannot allocate * memory in this memory, because it is used very early in the boot process. * * @param region Memory region * @param start The start of the virtual memory region to unmap. This value is * aligned down on pagesize. * @param size The size of the virtual memory region to unmap. This value is * aligned up on pagesize. * @return true for success, false otherwise. */ public abstract boolean munmap(int region, Address start, Extent size) throws UninterruptiblePragma; /** * Gets the memory map of the current system. If no map has yet been created, * it will be created by calling {@link #createMemoryMap()}. * * @return the architecture's memory map. */ public final MemoryMapEntry[] getMemoryMap() { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(MMAP_PERM); } if (memoryMap == null) { memoryMap = createMemoryMap(); } return memoryMap; } /** * Create the memory map of the current system. * * @return the memory map. */ protected abstract MemoryMapEntry[] createMemoryMap(); /** * Create a multi-media memory resource wrapping the given memory resource. * * @param res a memory resource * @return The created instance, which is never {@code null}. */ final MultiMediaMemoryResourceImpl createMultiMediaMemoryResource(MemoryResourceImpl res) { if (multiMediaSupport == null) { multiMediaSupport = createMultiMediaSupport(); } return new MultiMediaMemoryResourceImpl((MemoryResourceImpl) res, multiMediaSupport); } /** * Creates a multi-media support instance. The default implementation returns a * generic support instance. This method may be overriden to provide an architecture * optimized {@link VmMultiMediaSupport} implementation. * * @return a multi-media support instance. */ protected VmMultiMediaSupport createMultiMediaSupport() { return new VmJavaMultiMediaSupport(); } }