Commit e7eb5108 authored by Yi Lin's avatar Yi Lin

page protection

parent 3a544853
......@@ -25,7 +25,8 @@ public class Config {
public final int YIELDPOINT_IMPL;
public static final int USE_CHECKING_YP = 0;
public static final int USE_PAGE_PROTECTION_YP = 1;
public static final int USE_PAGE_PROTECTION_READ_YP = 1;
public static final int USE_PAGE_PROTECTION_WRITE_YP = 1;
public static final int USE_CODE_PATCHING_YP = 2;
public static final int USE_NO_YP = 9;
......@@ -34,8 +35,10 @@ public class Config {
HEADER_MARK_BITS = config.getBooleanProperty("mmtk.headerMarkBit",true);
if (config.getBooleanProperty("mmtk.use_checking_yp", false)) {
YIELDPOINT_IMPL = USE_CHECKING_YP;
} else if (config.getBooleanProperty("mmtk.use_page_protection_yp", false)) {
YIELDPOINT_IMPL = USE_PAGE_PROTECTION_YP;
} else if (config.getBooleanProperty("mmtk.use_page_protection_read_yp", false)) {
YIELDPOINT_IMPL = USE_PAGE_PROTECTION_READ_YP;
} else if (config.getBooleanProperty("mmtk.use_page_protection_write_yp", false)) {
YIELDPOINT_IMPL = USE_PAGE_PROTECTION_WRITE_YP;
} else if (config.getBooleanProperty("mmtk.use_code_patching_yp", false)) {
YIELDPOINT_IMPL = USE_CODE_PATCHING_YP;
} else if (config.getBooleanProperty("mmtk.use_no_yp", false)) {
......
#
# This file is part of the Jikes RVM project (http://jikesrvm.org).
#
# This file is licensed to You under the Eclipse Public License (EPL);
# You may not use this file except in compliance with the License. You
# may obtain a copy of the License at
#
# http://www.opensource.org/licenses/eclipse-1.0.php
#
# See the COPYRIGHT.txt file distributed with this work for information
# regarding copyright ownership.
#
# Default MMTk properties file.
mmtk.use_page_protection_yp = true
......@@ -174,6 +174,8 @@ public class VM extends Properties {
RVMThread.getCurrentThread().pthread_id = sysCall.sysGetThreadId();
RVMThread.getCurrentThread().priority_handle = sysCall.sysGetThreadPriorityHandle();
RVMThread.availableProcessors = SysCall.sysCall.sysNumProcessors();
// RVMThread.initYieldpoint();
// Set up buffer locks used by Thread for logging and status dumping.
// This can happen at any point before we start running
......
......@@ -259,6 +259,8 @@ public class RVMClassLoader {
public static final Atom StandardObjectFinalizerMethodName = Atom.findOrCreateAsciiAtom("finalize");
/** {@code ()V} */
public static final Atom StandardObjectFinalizerMethodDescriptor = Atom.findOrCreateAsciiAtom("()V");
public static final Atom YieldpointMethodName = Atom.findOrCreateAsciiAtom("yieldpointFromPrologue");
// Names of .class file attributes.
//
......
......@@ -301,6 +301,11 @@ public abstract class RVMMethod extends RVMMember {
public final boolean isObjectInitializerHelper() {
return getName() == RVMClassLoader.StandardObjectInitializerHelperMethodName;
}
@Uninterruptible
public final boolean isYieldpoint() {
return getName() == RVMClassLoader.YieldpointMethodName;
}
@Uninterruptible
public final TypeReference getReturnType() {
......
......@@ -3291,6 +3291,7 @@ public abstract class BaselineCompilerImpl extends BaselineCompiler implements B
* point of the caller.
* The third word of the header contains the compiled method id of the called method.
*/
asm.emitPUSH_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset()); // store caller's frame pointer
ThreadLocalState.emitMoveRegToField(asm,
ArchEntrypoints.framePointerField.getOffset(),
......@@ -3300,6 +3301,15 @@ public abstract class BaselineCompilerImpl extends BaselineCompiler implements B
*/
if (VM.VerifyAssertions) VM._assert(STACKFRAME_METHOD_ID_OFFSET == -WORDSIZE);
asm.emitPUSH_Imm(compiledMethod.getId());
// if (method.isYieldpoint()) {
// asm.emitMOV_RegDisp_Reg(ESI, Entrypoints.EAXSaveField.getOffset(), EAX);
// asm.emitMOV_RegDisp_Reg(ESI, Entrypoints.ECXSaveField.getOffset(), ECX);
// asm.emitMOV_RegDisp_Reg(ESI, Entrypoints.EDXSaveField.getOffset(), EAX);
//// asm.emitPUSH_Reg(EAX);
//// asm.emitPUSH_Reg(ECX);
//// asm.emitPUSH_Reg(EDX);
// }
/*
* save registers
......@@ -3318,6 +3328,8 @@ public abstract class BaselineCompilerImpl extends BaselineCompiler implements B
} else {
savedRegistersSize= SAVED_GPRS << LG_WORDSIZE; // default
}
/* handle "dynamic brige" methods:
* save all registers except FP, SP, TR, S0 (scratch), and
......@@ -3442,6 +3454,8 @@ public abstract class BaselineCompilerImpl extends BaselineCompiler implements B
* @param bytesPopped number of paramter bytes already released
*/
private void genEpilogue(int returnSize, int bytesPopped) {
if (klass.hasBridgeFromNativeAnnotation()) {
// pop locals and parameters, get to saved GPR's
adjustStack((method.getLocalWords() << LG_WORDSIZE)+(returnSize-bytesPopped), true);
......@@ -3465,7 +3479,19 @@ public abstract class BaselineCompilerImpl extends BaselineCompiler implements B
asm.emitPOP_Reg(EBX); // restore non-volatile EBX register
if (VM.VerifyAssertions) VM._assert(EDI_SAVE_OFFSET.toInt() == -(2 * WORDSIZE));
asm.emitPOP_Reg(EDI); // restore non-volatile EDI register
// if (method.isYieldpoint()) {
// asm.emitMOV_Reg_RegDisp(EAX, ESI, Entrypoints.EAXSaveField.getOffset());
// asm.emitMOV_Reg_RegDisp(ECX, ESI, Entrypoints.ECXSaveField.getOffset());
// asm.emitMOV_Reg_RegDisp(EDX, ESI, Entrypoints.EDXSaveField.getOffset());
//// asm.emitPOP_Reg(EDX);
//// asm.emitPOP_Reg(ECX);
//// asm.emitPOP_Reg(EAX);
//// asm.emitADD_Reg_Imm(SP, 4);
// }
//
adjustStack(WORDSIZE, true); // throw away CMID
// SP == frame pointer
asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset()); // discard frame
// return to caller, pop parameters from stack
......@@ -3925,6 +3951,10 @@ public abstract class BaselineCompilerImpl extends BaselineCompiler implements B
fr1.resolve(asm);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_NO_YP) {
// dont do anything
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_READ_YP) {
asm.emitTEST_Abs_Imm(RVMThread.PROTECT_GLOBAL_PAGE_BL, 0);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_WRITE_YP) {
asm.emitMOV_Abs_Imm(RVMThread.PROTECT_GLOBAL_PAGE_BL, 0);
}
if (VM.BuildForAdaptiveSystem && options.INVOCATION_COUNTERS) {
......
......@@ -82,6 +82,7 @@ import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_BACKEDGE_opcode
import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_EPILOGUE_opcode;
import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_OSR_opcode;
import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_PROLOGUE_opcode;
import static org.jikesrvm.compilers.opt.ir.Operators.IA32_TEST;
import org.jikesrvm.compilers.opt.ir.Register;
import org.jikesrvm.compilers.opt.ir.ia32.PhysicalDefUse;
......@@ -99,6 +100,7 @@ import org.jikesrvm.compilers.opt.mir2mc.MachineCodeOffsets;
import org.jikesrvm.runtime.ArchEntrypoints;
import org.jikesrvm.runtime.Entrypoints;
import org.jikesrvm.runtime.Magic;
import org.jikesrvm.scheduler.RVMThread;
import org.vmmagic.unboxed.Offset;
/**
......@@ -403,6 +405,10 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_NO_YP) {
// do nothing
removeYieldpoint(p, ir);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_READ_YP) {
expandPageProtectionReadYieldpoint(p, ir);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_WRITE_YP) {
expandPageProtectionWriteYieldpoint(p, ir);
}
break;
......@@ -412,6 +418,10 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_NO_YP) {
// do nothing
removeYieldpoint(p, ir);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_READ_YP) {
expandPageProtectionReadYieldpoint(p, ir);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_WRITE_YP) {
expandPageProtectionWriteYieldpoint(p, ir);
}
break;
......@@ -421,6 +431,10 @@ public class FinalMIRExpansion extends IRTools {
else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_NO_YP) {
// do nothing
removeYieldpoint(p, ir);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_READ_YP) {
expandPageProtectionReadYieldpoint(p, ir);
} else if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_WRITE_YP) {
expandPageProtectionWriteYieldpoint(p, ir);
}
break;
......@@ -434,6 +448,16 @@ public class FinalMIRExpansion extends IRTools {
return 0;
}
private static void expandPageProtectionReadYieldpoint(Instruction p, IR ir) {
Operand mem = MemoryOperand.D(RVMThread.PROTECT_GLOBAL_PAGE_OPT, (byte) 4, null, null);
MIR_Test.mutate(p, IA32_TEST, mem, IC(0));
}
private static void expandPageProtectionWriteYieldpoint(Instruction p, IR ir) {
Operand mem = MemoryOperand.D(RVMThread.PROTECT_GLOBAL_PAGE_OPT, (byte) 4, null, null);
MIR_Move.mutate(p, IA32_MOV, mem, IC(0));
}
private static void removeYieldpoint(Instruction s, IR ir) {
s.remove();
ir.MIRInfo.gcIRMap.delete(s);
......
......@@ -202,6 +202,10 @@ public class BootRecord {
* jtoc offset of RVMThread.debugRequested
*/
Offset debugRequestedOffset;
public Offset yieldpointFromPrologueOffset;
public Offset yieldpointFromPrologueOptOffset;
/**
* an external signal has been sent e.g. kill -signalnumber processid
*/
......
......@@ -191,6 +191,12 @@ public class Entrypoints {
getField(org.jikesrvm.scheduler.RVMThread.class, "scratchStorage", double.class);
public static final RVMField takeYieldpointField =
getField(org.jikesrvm.scheduler.RVMThread.class, "takeYieldpoint", int.class);
public static final RVMField EAXSaveField =
getField(org.jikesrvm.scheduler.RVMThread.class, "EAXSave", int.class);
public static final RVMField ECXSaveField =
getField(org.jikesrvm.scheduler.RVMThread.class, "ECXSave", int.class);
public static final RVMField EDXSaveField =
getField(org.jikesrvm.scheduler.RVMThread.class, "EDXSave", int.class);
public static final RVMField execStatusField = getField(org.jikesrvm.scheduler.RVMThread.class, "execStatus", int.class);
......
......@@ -910,6 +910,10 @@ public class RuntimeEntrypoints implements ArchitectureSpecific.StackframeLayout
BootRecord.the_boot_record.hardwareTrapMethodId = CompiledMethods.createHardwareTrapCompiledMethod().getId();
BootRecord.the_boot_record.deliverHardwareExceptionOffset =
Entrypoints.deliverHardwareExceptionMethod.getOffset();
BootRecord.the_boot_record.yieldpointFromPrologueOffset = Entrypoints.yieldpointFromPrologueMethod.getOffset();
if (VM.BuildForOptCompiler) {
BootRecord.the_boot_record.yieldpointFromPrologueOptOffset = Entrypoints.optThreadSwitchFromPrologueMethod.getOffset();
}
// tell "RunBootImage.C" to set "RVMThread.debugRequested" flag
// whenever the host operating system detects a debug request signal
......
......@@ -23,16 +23,19 @@ import java.security.PrivilegedAction;
import org.jikesrvm.ArchitectureSpecific.CodeArray;
import org.jikesrvm.ArchitectureSpecific.Registers;
import org.jikesrvm.ArchitectureSpecificOpt.PostThreadSwitch;
import static org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants.STACK_SIZE_NORMAL;
import static org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants.INVISIBLE_METHOD_ID;
import static org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants.STACKFRAME_SENTINEL_FP;
import static org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants.STACK_SIZE_GUARD;
import static org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants.STACKFRAME_METHOD_ID_OFFSET;
import static org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants.STACKFRAME_RETURN_ADDRESS_OFFSET;
import org.jikesrvm.ArchitectureSpecific.BaselineConstants;
import org.jikesrvm.ArchitectureSpecific.ThreadLocalState;
import org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants;
import org.jikesrvm.ArchitectureSpecific;
import org.jikesrvm.SizeConstants;
import org.jikesrvm.VM;
import org.jikesrvm.Configuration;
import org.jikesrvm.Services;
......@@ -70,10 +73,12 @@ import org.vmmagic.pragma.UnpreemptibleNoWarn;
import org.vmmagic.pragma.Untraced;
import org.vmmagic.pragma.NoCheckStore;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Extent;
import org.vmmagic.unboxed.Word;
import org.vmmagic.unboxed.Offset;
import static org.jikesrvm.runtime.SysCall.sysCall;
import org.jikesrvm.classloader.RVMMethod;
import org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod;
import org.jikesrvm.compilers.opt.runtimesupport.OptMachineCodeMap;
......@@ -509,6 +514,15 @@ public final class RVMThread extends ThreadContext {
*/
@Entrypoint
Address framePointer;
@Entrypoint
int EAXSave;
@Entrypoint
int ECXSave;
@Entrypoint
int EDXSave;
/**
* "hidden parameter" for interface invocation thru the IMT
......@@ -965,7 +979,7 @@ public final class RVMThread extends ThreadContext {
*/
@Entrypoint
public int takeYieldpoint;
/**
* How many times has the "timeslice" expired? This is only used for profiling
* and OSR (in particular base-to-opt OSR).
......@@ -3821,6 +3835,8 @@ public final class RVMThread extends ThreadContext {
// Deal with terminating threads to ensure that all threads are either dead to MMTk or stopped above.
RVMThread.processAboutToTerminate();
turnOffYieldpoints();
}
/**
......@@ -5592,11 +5608,23 @@ public final class RVMThread extends ThreadContext {
sloppyExecStatusHistogram[newState]++;
}
public static final Address PROTECT_GLOBAL_PAGE_BL = Address.fromIntSignExtend(0x50000000);
public static final Address PROTECT_GLOBAL_PAGE_OPT = PROTECT_GLOBAL_PAGE_BL.plus(4);
public static final Extent PROTECT_PAGE_SIZE = Extent.fromIntSignExtend(SizeConstants.BYTES_IN_PAGE);
public static void turnOnYieldpoints() {
VM.sysWriteln("Turn on yieldpoints");
if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_READ_YP ||
org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_WRITE_YP) {
Memory.mprotect(PROTECT_GLOBAL_PAGE_BL, PROTECT_PAGE_SIZE, Memory.PROT_NONE);
}
}
public static void turnOffYieldpoints() {
VM.sysWriteln("Turn off yieldpoints");
if (org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_READ_YP ||
org.mmtk.vm.VM.config.YIELDPOINT_IMPL == org.mmtk.vm.Config.USE_PAGE_PROTECTION_WRITE_YP) {
Memory.mprotect(PROTECT_GLOBAL_PAGE_BL, PROTECT_PAGE_SIZE, Memory.PROT_EXEC | Memory.PROT_READ | Memory.PROT_WRITE);
}
}
}
......@@ -442,6 +442,13 @@ public class GenerateInterfaceDeclarations {
//
pln("ObjectModel_ARRAY_LENGTH_OFFSET = ", ObjectModel.getArrayLengthOffset());
pln();
// yieldpoint
p("static const int YIELDPOINT_IMPL = " + org.mmtk.vm.VM.config.YIELDPOINT_IMPL + ";\n");
p("static const unsigned int PROTECT_GLOBAL_PAGE_BL = " + RVMThread.PROTECT_GLOBAL_PAGE_BL + ";\n");
p("static const unsigned int PROTECT_GLOBAL_PAGE_OPT = " + RVMThread.PROTECT_GLOBAL_PAGE_OPT + ";\n");
p("static const unsigned int PROTECT_PAGE_SIZE = " + RVMThread.PROTECT_PAGE_SIZE + ";\n");
pln();
// values in RuntimeEntrypoints
//
......
......@@ -647,7 +647,33 @@ hardwareTrapHandler(int signo, siginfo_t *si, void *context)
// We should never get here.
_exit(EXIT_STATUS_DYING_WITH_UNCAUGHT_EXCEPTION);
}
/* page protection yieldpoint */
if (YIELDPOINT_IMPL == 1 || YIELDPOINT_IMPL == 2) {
unsigned int faultAddress = (unsigned int) si->si_addr;
if (faultAddress == PROTECT_GLOBAL_PAGE_BL || faultAddress == PROTECT_GLOBAL_PAGE_OPT) {
if (lib_verbose) {
printf("Thread %x in exception handler\n", IA32_ESI(context));
}
// adjust stack
Address* sp = (Address*) (IA32_ESP(context) - 4);
IA32_ESP(context) = IA32_ESP(context) - 4;
instructionFollowing = getInstructionFollowing(localInstructionAddress);
*sp = instructionFollowing;
// get handler address
unsigned int yieldpointHandlerAddress;
if (faultAddress == PROTECT_GLOBAL_PAGE_BL)
yieldpointHandlerAddress = *(unsigned int*) (localJTOC + bootRecord->yieldpointFromPrologueOffset);
else
yieldpointHandlerAddress = *(unsigned int*) (localJTOC + bootRecord->yieldpointFromPrologueOptOffset);
IA32_EIP(context) = yieldpointHandlerAddress;
return;
}
}
int HardwareTrapMethodId = bootRecord->hardwareTrapMethodId;
unsigned int javaExceptionHandlerAddress =
......@@ -931,6 +957,23 @@ mapImageFile(const char *fileName, const void *targetAddress, int prot,
fseek (fin, 0L, SEEK_SET);
void *bootRegion = 0;
if (YIELDPOINT_IMPL == 1 || YIELDPOINT_IMPL == 2) {
if ((unsigned int)targetAddress == 0x60000000) {
bootRegion = mmap((void*)PROTECT_GLOBAL_PAGE_BL, 4096, prot, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
if (bootRegion == (void*) MAP_FAILED) {
printf("mmap failed\n");
return 0;
}
printf("mmap on %x\n", bootRegion);
*(int*)bootRegion = 0;
}
}
bootRegion = 0;
bootRegion = mmap((void*)targetAddress, *roundedImageSize,
prot,
MAP_FIXED | MAP_PRIVATE | MAP_NORESERVE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment