/*
* $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.io.PrintWriter;
import java.io.StringWriter;
import org.jnode.annotation.Inline;
import org.jnode.annotation.Internal;
import org.jnode.annotation.KernelSpace;
import org.jnode.annotation.MagicPermission;
import org.jnode.assembler.ObjectResolver;
import org.jnode.permission.JNodePermission;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.facade.VmUtils;
import org.jnode.vm.scheduler.VmProcessor;
import org.jnode.vm.scheduler.VmThread;
import org.vmmagic.pragma.UninterruptiblePragma;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Extent;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.Offset;
import org.vmmagic.unboxed.Word;
/**
* Class that allows directy hardware access.
*
* @author epr
*/
@MagicPermission
public final class Unsafe {
private static final JNodePermission GET_JUMP_TABLE_PERM = new JNodePermission(
"getJumpTable");
@MagicPermission
public static class UnsafeObjectResolver extends ObjectResolver {
public UnsafeObjectResolver() {
}
/**
* @param object
* @return int
* @see org.jnode.assembler.ObjectResolver#addressOf32(Object)
*/
public int addressOf32(Object object) {
return ObjectReference.fromObject(object).toAddress().toInt();
}
/**
* @param object
* @return long
* @see org.jnode.assembler.ObjectResolver#addressOf64(Object)
*/
public long addressOf64(Object object) {
return ObjectReference.fromObject(object).toAddress().toLong();
}
}
/**
* Gets the Super Classes Array of the given object.
*
* @param object
* @return VmType[]
*/
protected static native VmType[] getSuperClasses(Object object);
/**
* Sets a byte at a given memory address While count is greater then 1, the
* address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setBytes(Address memPtr, byte value, int count);
/**
* Perform a bitwise AND of the byte at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void andByte(Address memPtr, byte value, int count);
/**
* Perform a bitwise OR of the byte at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void orByte(Address memPtr, byte value, int count);
/**
* Perform a bitwise XOR of the byte at the given address and the given
* value While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void xorByte(Address memPtr, byte value, int count);
/**
* Sets a short at a given memory address While count is greater then 1, the
* address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setShorts(Address memPtr, short value,
int count);
/**
* Perform a bitwise AND of the short at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void andShort(Address memPtr, short value, int count);
/**
* Perform a bitwise OR of the short at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void orShort(Address memPtr, short value, int count);
/**
* Perform a bitwise XOR of the short at the given address and the given
* value While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void xorShort(Address memPtr, short value, int count);
/**
* Sets a char at a given memory address While count is greater then 1, the
* address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setChars(Address memPtr, char value, int count);
/**
* Perform a bitwise AND of the char at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void andChar(Address memPtr, char value, int count);
/**
* Perform a bitwise OR of the char at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void orChar(Address memPtr, char value, int count);
/**
* Perform a bitwise XOR of the char at the given address and the given
* value While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void xorChar(Address memPtr, char value, int count);
/**
* Sets an int at a given memory address While count is greater then 1, the
* address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setInts(Address memPtr, int value, int count);
/**
* Perform a bitwise AND of the int at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void andInt(Address memPtr, int value, int count);
/**
* Perform a bitwise OR of the int at the given address and the given value.
* While count is greater then 1, the address is incremented and the process
* repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void orInt(Address memPtr, int value, int count);
/**
* Perform a bitwise XOR of the int at the given address and the given value
* While count is greater then 1, the address is incremented and the process
* repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void xorInt(Address memPtr, int value, int count);
/**
* Sets a 24-bit int at a given memory address While count is greater then
* 1, the address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setInts24(Address memPtr, int value, int count);
/**
* Perform a bitwise AND of the 24-bit int at the given address and the
* given value. While count is greater then 1, the address is incremented
* and the process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void andInt24(Address memPtr, int value, int count);
/**
* Perform a bitwise OR of the 24-bit int at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void orInt24(Address memPtr, int value, int count);
/**
* Perform a bitwise XOR of the 24-bit int at the given address and the
* given value While count is greater then 1, the address is incremented and
* the process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void xorInt24(Address memPtr, int value, int count);
/**
* Sets a long at a given memory address While count is greater then 1, the
* address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setLongs(Address memPtr, long value, int count);
/**
* Perform a bitwise AND of the long at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void andLong(Address memPtr, long value, int count);
/**
* Perform a bitwise OR of the long at the given address and the given
* value. While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void orLong(Address memPtr, long value, int count);
/**
* Perform a bitwise XOR of the long at the given address and the given
* value While count is greater then 1, the address is incremented and the
* process repeats.
*
* @param memPtr
* @param value
* @param count The number of times to repeat this operation
*/
protected static native void xorLong(Address memPtr, long value, int count);
/**
* Sets a float at a given memory address While count is greater then 1, the
* address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setFloats(Address memPtr, float value,
int count);
/**
* Sets a double at a given memory address While count is greater then 1,
* the address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setDoubles(Address memPtr, double value,
int count);
/**
* Sets a Object at a given memory address While count is greater then 1,
* the address is incremented and the process repeats.
*
* @param memPtr
* @param value
* @param count
*/
protected static native void setObjects(Address memPtr, Object value,
int count);
/**
* Fill the memory at the given memory address with size times 0 bytes.
* <p/>
* memPtr must be VmObject.SLOT_SIZE aligned
* <p/>
* size % VmObject.SLOT_SIZE must be 0
*
* @param memPtr
* @param size
*/
protected static native void clear(Address memPtr, Extent size);
/**
* Copy size bytes of memory from srcMemPtr to destMemPtr. The memory areas
* must not overlap.
*
* @param srcMemPtr
* @param destMemPtr
* @param size
*/
protected static native void copy(Address srcMemPtr, Address destMemPtr,
Extent size);
/**
* Push an integer onto the execution stack
*
* @param value
*/
protected static native void pushInt(int value);
/**
* Push a long onto the execution stack
*
* @param value
*/
protected static native void pushLong(long value);
/**
* Push an Object onto the execution stack
*
* @param value
*/
protected static native void pushObject(Object value);
/**
* Invoke the given method without any parameters
*
* @param method
*/
protected static native void invokeVoid(VmMethod method);
/**
* Invoke the given method without any parameters
*
* @param method
* @return int
*/
protected static native int invokeInt(VmMethod method);
/**
* Invoke the given method without any parameters
*
* @param method
* @return long
*/
protected static native long invokeLong(VmMethod method);
/**
* Invoke the given method without any parameters
*
* @param method
* @return Object
*/
protected static native Object invokeObject(VmMethod method);
/**
* Halt the processor until the next interrupt arrives.
*/
@Internal
public static native void idle();
/**
* Cause the system to stop TODO Protect me again
*/
@KernelSpace
public static void die(String msg) {
debug("Real panic: ");
if (msg != null) {
debug(msg);
}
die();
}
/**
* Cause the system to stop TODO Protect me again
*/
@KernelSpace
private static native void die();
/**
* Print the given string on the screen.
*/
@KernelSpace
public static native void debug(String str);
/**
* Print the given value on the screen.
*/
@KernelSpace
public static native void debug(char value);
/**
* Print the given value on the screen.
*/
@KernelSpace
public static native void debug(int value);
/**
* Print the given value on the screen.
*/
@KernelSpace
public static native void debug(long value);
/**
* Print the given value on the screen.
*/
public static final void debug(boolean value) {
debug(value ? "true" : "false");
}
/**
* Print the given value on the screen.
*/
@KernelSpace
public static native void debug(Address value);
/**
* Print the given value on the screen.
*/
@KernelSpace
public static native void debug(Word value);
/**
* Print the given value on the screen.
*/
@KernelSpace
public static native void debug(Extent value);
/**
* Print the given value on the screen.
*/
@KernelSpace
public static native void debug(Offset value);
/**
* Enable/Disable the kernel debugger.
*
* @return the previous enabled state.
*/
public static native boolean setKdbEnabled(boolean on);
/**
* Is the kernel debugger enabled?
*/
@KernelSpace
public static native boolean isKdbEnabled();
/**
* Read a single byte from the kernel debugger input queue.
*
* @return The byte, or -1 if no data available.
*/
@KernelSpace
@Internal
public static native int readKdbInput();
/**
* Initialize the new Thread.
*
* @param curThread
* @param newStack
* @param stackSize
*/
@Internal
public static native void initThread(VmThread curThread,
Object newStack, int stackSize);
protected static native int inPortByte(int portNr);
protected static native int inPortWord(int portNr);
protected static native int inPortDword(int portNr);
protected static native void outPortByte(int portNr, int value);
protected static native void outPortWord(int portNr, int value);
protected static native void outPortDword(int portNr, int value);
/**
* Gets the minimum valid address in the addressspace of the current
* architecture.
*
* @return Address
*/
protected static native Address getMinAddress();
/**
* Gets the maximum valid address in the addressspace of the current
* architecture.
*
* @return Address
*/
protected static native Address getMaxAddress();
/**
* Gets the (inclusive) start address of the available memory.
*
* @return Address
*/
protected static native Address getMemoryStart();
/**
* Gets the (exclusive) end address of the available memory.
*
* @return Address
*/
protected static native Address getMemoryEnd();
/**
* Gets the (inclusive) start address of the kernel.
*
* @return Address
*/
protected static native Address getKernelStart();
/**
* Gets the (exclusive) end address of the kernel.
*
* @return Address
*/
protected static native Address getKernelEnd();
/**
* Gets the (inclusive) start address of the initial jarfile.
*
* @return Address
*/
protected static native Address getInitJarStart();
/**
* Gets the (exclusive) end address of the initial jarfile.
*
* @return Address
*/
protected static native Address getInitJarEnd();
/**
* Gets the (inclusive) start address of the boot heap.
*
* @return Address
*/
protected static native Address getBootHeapStart();
/**
* Gets the (exclusive) end address of the boot heap.
*
* @return Address
*/
protected static native Address getBootHeapEnd();
/**
* Gets information of the JNode kernel command line.
*
* @param destination If non-null, the commandline is copied into this array.
* @return The maximum length of the command line
*/
protected static native int getCmdLine(byte[] destination);
/**
* Trigger a yieldpoint
*/
public static native void yieldPoint();
/**
* Gets the address of the system dependent jump table used for native
* method indirection.
*
* @return The address of the system dependent jump table.
*/
private static native Address getJumpTable0();
/**
* Gets the address of the system dependent jump table used for native
* method indirection.
*
* @return The address of the system dependent jump table.
*/
public static final Address getJumpTable() {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(GET_JUMP_TABLE_PERM);
}
return getJumpTable0();
}
/**
* Gets a jumptable entry. This method can only be called at runtime.
*
* @param index
* @return The jumptable entry.
*/
public static final Address getJumpTableEntry(int index) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(GET_JUMP_TABLE_PERM);
}
final int offset = index * VmUtils.getVm().getArch().getReferenceSize();
return getJumpTable0().loadAddress(Offset.fromIntSignExtend(offset));
}
/**
* List the current stacktrace on the kernel debug output.
*
* @throws UninterruptiblePragma
*/
@Inline
public static final void debugStackTrace() throws UninterruptiblePragma {
VmProcessor.current().getArchitecture().getStackReader()
.debugStackTrace();
}
/**
* List the current stacktrace on the kernel debug output.
*
* @throws UninterruptiblePragma
*/
@Inline
public static final void debugStackTrace(String message, Throwable t) throws UninterruptiblePragma {
Unsafe.debug(message);
Unsafe.debug("\n");
Unsafe.debugStackTrace(t);
}
/**
* List the current stacktrace on the kernel debug output.
*
* @throws UninterruptiblePragma
*/
@Inline
public static final void debugStackTrace(Throwable t) throws UninterruptiblePragma {
Unsafe.debug(t.getMessage());
Unsafe.debug("\n");
StringWriter w = new StringWriter();
t.printStackTrace(new PrintWriter(w));
Unsafe.debug(w.toString());
}
/**
* List the current stacktrace on the kernel debug output.
*
* @throws UninterruptiblePragma
*/
@Inline
public static final void debugStackTrace(int max)
throws UninterruptiblePragma {
VmProcessor.current().getArchitecture().getStackReader()
.debugStackTrace(max);
}
/**
* return a nanosecond accurate timer based on the clock cycles
* of the CPU
*
* @return nanosecond accurate time
*/
public static native long getCpuCycles();
/**
* <b>DO NOT USE THIS METHOD</b> : it's bogus (especially for 64 bits CPU) and has not yet been tested
*
* @param codePtr
* @param function
* @param bufferPtr
* @return not telling.
* @deprecated this method is bogus.
*/
public static native int callVbeFunction(Address codePtr, int function, Address bufferPtr);
}