Skip to content

Commit

Permalink
Support the loading of an EBOOT.BIN in kernel mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
gid15 committed Apr 21, 2015
1 parent 34dc015 commit bd06360
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 23 deletions.
18 changes: 9 additions & 9 deletions src/jpcsp/Allegrex/compiler/RuntimeContext.java
Expand Up @@ -791,7 +791,9 @@ public static void addCodeBlock(int address, CodeBlock codeBlock) {
computeCodeBlocksRange();

int fastExecutableLoopukIndex = (address - MemoryMap.START_USERSPACE) >> 2;
fastExecutableLookup[fastExecutableLoopukIndex] = null;
if (fastExecutableLoopukIndex >= 0 && fastExecutableLoopukIndex < fastExecutableLookup.length) {
fastExecutableLookup[fastExecutableLoopukIndex] = null;
}
} else {
// One new code block has been added, update the code blocks range
codeBlocksLowestAddress = Math.min(codeBlocksLowestAddress, codeBlock.getLowestAddress());
Expand All @@ -815,11 +817,11 @@ public static Map<Integer, CodeBlock> getCodeBlocks() {
public static IExecutable getExecutable(int address) {
// Check if we have already the executable in the fastExecutableLookup array
int fastExecutableLoopukIndex = (address - MemoryMap.START_USERSPACE) >> 2;
IExecutable executable = null;
try {
IExecutable executable;
if (fastExecutableLoopukIndex >= 0 && fastExecutableLoopukIndex < fastExecutableLookup.length) {
executable = fastExecutableLookup[fastExecutableLoopukIndex];
} catch (ArrayIndexOutOfBoundsException e) {
// Ignore exception
} else {
executable = null;
}

if (executable == null) {
Expand All @@ -831,11 +833,9 @@ public static IExecutable getExecutable(int address) {
}

// Store the executable in the fastExecutableLookup array
try {
if (fastExecutableLoopukIndex >= 0 && fastExecutableLoopukIndex < fastExecutableLookup.length) {
fastExecutableLookup[fastExecutableLoopukIndex] = executable;
} catch (ArrayIndexOutOfBoundsException e) {
// Ignore exception
}
}
}

return executable;
Expand Down
2 changes: 2 additions & 0 deletions src/jpcsp/HLE/kernel/types/SceModule.java
Expand Up @@ -31,6 +31,8 @@
import jpcsp.util.Utilities;

public class SceModule {
public static final int PSP_MODULE_VSH = 0x0800;
public static final int PSP_MODULE_KERNEL = 0x1000;
// PSP info
public int next; // should be handled by a manager
public short attribute;
Expand Down
28 changes: 17 additions & 11 deletions src/jpcsp/HLE/modules150/ThreadManForUser.java
Expand Up @@ -200,8 +200,9 @@ public String getName() {
public static final int NET_ADHOC_MATCHING_EVENT_LOOP_ADDRESS = INTERNAL_THREAD_ADDRESS_START + 0x50;
public static final int NET_ADHOC_MATCHING_INPUT_LOOP_ADDRESS = INTERNAL_THREAD_ADDRESS_START + 0x60;
public static final int NET_ADHOC_CTL_LOOP_ADDRESS = INTERNAL_THREAD_ADDRESS_START + 0x70;
public static final int INTERNAL_THREAD_ADDRESS_END = INTERNAL_THREAD_ADDRESS_START + 0x80;
public static final int UTILITY_LOOP_ADDRESS = INTERNAL_THREAD_ADDRESS_START + 0x90;
public static final int UTILITY_LOOP_ADDRESS = INTERNAL_THREAD_ADDRESS_START + 0x80;
public static final int INTERNAL_THREAD_ADDRESS_END = INTERNAL_THREAD_ADDRESS_START + 0x90;
public static final int INTERNAL_THREAD_ADDRESS_SIZE = INTERNAL_THREAD_ADDRESS_END - INTERNAL_THREAD_ADDRESS_START;
private HashMap<Integer, SceKernelCallbackInfo> callbackMap;
private static final boolean LOG_CONTEXT_SWITCHING = true;
private static final boolean LOG_INSTRUCTIONS = false;
Expand Down Expand Up @@ -247,7 +248,7 @@ public void start() {
callbackManager.Initialize();

// Reserve the memory user the internal handlers
Modules.SysMemUserForUserModule.malloc(SysMemUserForUser.KERNEL_PARTITION_ID, "ThreadMan-InternalHandlers", SysMemUserForUser.PSP_SMEM_Addr, 0x100, MemoryMap.START_RAM);
Modules.SysMemUserForUserModule.malloc(SysMemUserForUser.KERNEL_PARTITION_ID, "ThreadMan-InternalHandlers", SysMemUserForUser.PSP_SMEM_Addr, INTERNAL_THREAD_ADDRESS_SIZE, INTERNAL_THREAD_ADDRESS_START);
installIdleThreads();
installThreadExitHandler();
installCallbackExitHandler();
Expand Down Expand Up @@ -313,6 +314,9 @@ public void Initialise(SceModule module, int entry_addr, int attr, String pspfil
rootStackSize = module.module_start_thread_stacksize;
}

// For a kernel module, the stack is allocated in the kernel partition
int rootMpidStack = module.mpiddata > 0 ? module.mpiddata : USER_PARTITION_ID;

int rootInitPriority = 0x20;
// Use the module_start_thread_priority when this information was present in the ELF file
if (module != null && module.module_start_thread_priority > 0) {
Expand All @@ -321,7 +325,7 @@ public void Initialise(SceModule module, int entry_addr, int attr, String pspfil
if (log.isDebugEnabled()) {
log.debug(String.format("Creating root thread: entry=0x%08X, priority=%d, stackSize=0x%X, attr=0x%X", entry_addr, rootInitPriority, rootStackSize, attr));
}
currentThread = new SceKernelThreadInfo("root", entry_addr, rootInitPriority, rootStackSize, attr, USER_PARTITION_ID);
currentThread = new SceKernelThreadInfo("root", entry_addr, rootInitPriority, rootStackSize, attr, rootMpidStack);
currentThread.moduleid = moduleid;
threadMap.put(currentThread.uid, currentThread);

Expand Down Expand Up @@ -3136,20 +3140,22 @@ public int sceKernelReferVTimerStatus(@CheckArgument("checkVTimerID") int vtimer

@HLEFunction(nid = 0x446D8DE6, version = 150)
public int sceKernelCreateThread(@StringInfo(maxLength = 32) String name, int entry_addr, int initPriority, int stackSize, int attr, int option_addr) {
SceKernelThreadInfo thread = hleKernelCreateThread(name, entry_addr, initPriority, stackSize, attr, option_addr, USER_PARTITION_ID);
int mpidStack = USER_PARTITION_ID;
// Inherit kernel mode if user mode bit is not set
if (currentThread.isKernelMode() && !SceKernelThreadInfo.isUserMode(attr)) {
log.debug("sceKernelCreateThread inheriting kernel mode");
attr |= PSP_THREAD_ATTR_KERNEL;
mpidStack = KERNEL_PARTITION_ID;
}

SceKernelThreadInfo thread = hleKernelCreateThread(name, entry_addr, initPriority, stackSize, attr, option_addr, mpidStack);

if (thread.stackSize > 0 && thread.getStackAddr() == 0) {
log.warn("sceKernelCreateThread not enough memory to create the stack");
hleDeleteThread(thread);
return SceKernelErrors.ERROR_KERNEL_NO_MEMORY;
}

// Inherit kernel mode if user mode bit is not set
if (currentThread.isKernelMode() && !SceKernelThreadInfo.isUserMode(thread.attr)) {
log.debug("sceKernelCreateThread inheriting kernel mode");
thread.attr |= PSP_THREAD_ATTR_KERNEL;
}

// Inherit user mode
if (currentThread.isUserMode()) {
if (!SceKernelThreadInfo.isUserMode(thread.attr)) {
Expand Down
13 changes: 11 additions & 2 deletions src/jpcsp/Loader.java
Expand Up @@ -42,6 +42,7 @@
import jpcsp.HLE.kernel.Managers;
import jpcsp.HLE.kernel.types.SceModule;
import jpcsp.HLE.modules.SysMemUserForUser;
import jpcsp.HLE.modules.ThreadManForUser;
import jpcsp.HLE.modules150.SysMemUserForUser.SysMemInfo;
import jpcsp.format.DeferredStub;
import jpcsp.format.DeferredVStub32;
Expand Down Expand Up @@ -348,6 +349,14 @@ private boolean LoadELF(ByteBuffer f, SceModule module, int baseAddress, boolean
return false;
}

if (elf.isKernelMode()) {
module.mpidtext = SysMemUserForUser.KERNEL_PARTITION_ID;
module.mpiddata = SysMemUserForUser.KERNEL_PARTITION_ID;
if (!analyzeOnly && baseAddress == MemoryMap.START_USERSPACE + 0x4000) {
baseAddress = MemoryMap.START_RAM + Utilities.alignUp(ThreadManForUser.INTERNAL_THREAD_ADDRESS_SIZE, SysMemUserForUser.defaultSizeAlignment - 1);
}
}

if (elf.getHeader().isPRXDetected()) {
log.debug("Loader: Relocation required (PRX)");
module.fileFormat |= FORMAT_PRX;
Expand Down Expand Up @@ -707,10 +716,10 @@ private void LoadELFModuleInfo(ByteBuffer f, SceModule module, int baseAddress,
log.info(String.format("Found ModuleInfo at 0x%08X, name:'%s', version: %02X%02X, attr: 0x%08X, gp: 0x%08X", moduleInfoAddr, module.modname, module.version[1], module.version[0], module.attribute, module.gp_value));
}

if ((module.attribute & 0x1000) != 0) {
if ((module.attribute & SceModule.PSP_MODULE_KERNEL) != 0) {
log.warn("Kernel mode module detected");
}
if ((module.attribute & 0x0800) != 0) {
if ((module.attribute & SceModule.PSP_MODULE_VSH) != 0) {
log.warn("VSH mode module detected");
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/jpcsp/format/Elf32.java
Expand Up @@ -28,6 +28,7 @@
public class Elf32 {
// File offset
private int elfOffset;
private boolean kernelMode;

// Headers
private Elf32Header header;
Expand Down Expand Up @@ -72,7 +73,8 @@ private void loadProgramHeaders(ByteBuffer f) throws IOException {

// yapspd: if the PRX file is a kernel module then the most significant
// bit must be set in the phsyical address of the first program header.
if (i == 0 && (phdr.getP_paddr() & 0x80000000L) == 0x80000000L) {
if (i == 0 && (phdr.getP_paddr() & 0x80000000) != 0) {
kernelMode = true;
Emulator.log.debug("Kernel mode PRX detected");
}
}
Expand Down Expand Up @@ -186,4 +188,8 @@ public String getProgInfo() {
public String getSectInfo() {
return SectInfo;
}

public boolean isKernelMode() {
return kernelMode;
}
}

0 comments on commit bd06360

Please sign in to comment.