GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

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