Skip to content

Commit

Permalink
sceKernelLoadModule: allow loading of modules in kernel partition
Browse files Browse the repository at this point in the history
  • Loading branch information
gid15 committed Apr 19, 2015
1 parent 56b7cf5 commit 5c90f1b
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 27 deletions.
4 changes: 3 additions & 1 deletion src/jpcsp/Emulator.java
Expand Up @@ -16,6 +16,8 @@
*/
package jpcsp;

import static jpcsp.HLE.modules150.SysMemUserForUser.USER_PARTITION_ID;

import java.io.IOException;
import java.nio.ByteBuffer;

Expand Down Expand Up @@ -155,7 +157,7 @@ public SceModule load(String pspfilename, ByteBuffer f, boolean fromSyscall) thr

initNewPsp(fromSyscall);

module = jpcsp.Loader.getInstance().LoadModule(pspfilename, f, MemoryMap.START_USERSPACE + 0x4000, false);
module = Loader.getInstance().LoadModule(pspfilename, f, MemoryMap.START_USERSPACE + 0x4000, USER_PARTITION_ID, USER_PARTITION_ID, false);

if ((module.fileFormat & Loader.FORMAT_ELF) != Loader.FORMAT_ELF) {
throw new GeneralJpcspException("File format not supported!");
Expand Down
8 changes: 6 additions & 2 deletions src/jpcsp/HLE/kernel/types/SceKernelThreadInfo.java
Expand Up @@ -246,7 +246,7 @@ public String toString() {
}
}

public SceKernelThreadInfo(String name, int entry_addr, int initPriority, int stackSize, int attr) {
public SceKernelThreadInfo(String name, int entry_addr, int initPriority, int stackSize, int attr, int mpidStack) {
if (stackSize < 512) {
// 512 byte min. (required for interrupts)
stackSize = 512;
Expand All @@ -255,14 +255,18 @@ public SceKernelThreadInfo(String name, int entry_addr, int initPriority, int st
stackSize = (stackSize + 0xFF) & ~0xFF;
}

if (mpidStack == 0) {
mpidStack = SysMemUserForUser.USER_PARTITION_ID;
}

this.name = name;
this.entry_addr = entry_addr;
this.initPriority = initPriority;
this.stackSize = stackSize;
this.attr = attr;
uid = SceUidManager.getNewUid("ThreadMan-thread");
// Setup the stack.
stackSysMemInfo = Modules.SysMemUserForUserModule.malloc(SysMemUserForUser.USER_PARTITION_ID, String.format("ThreadMan-Stack-0x%x-%s", uid, name), SysMemUserForUser.PSP_SMEM_High, stackSize, 0);
stackSysMemInfo = Modules.SysMemUserForUserModule.malloc(mpidStack, String.format("ThreadMan-Stack-0x%x-%s", uid, name), SysMemUserForUser.PSP_SMEM_High, stackSize, 0);
if (stackSysMemInfo == null) {
stackAddr = 0;
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/jpcsp/HLE/modules150/IoFileMgrForUser.java
Expand Up @@ -1321,7 +1321,7 @@ private void startIoAsync(IoInfo info, long result, IoOperation ioOperation, IAc

info.asyncThread = threadMan.hleKernelCreateThread("SceIofileAsync",
ThreadManForUser.ASYNC_LOOP_ADDRESS, asyncPriority, stackSize,
threadMan.getCurrentThread().attr, 0);
threadMan.getCurrentThread().attr, 0, SysMemUserForUser.USER_PARTITION_ID);
if (log.isDebugEnabled()) {
log.debug(String.format("Starting Async IO thread %s", info.asyncThread));
}
Expand Down
31 changes: 21 additions & 10 deletions src/jpcsp/HLE/modules150/ModuleMgrForUser.java
Expand Up @@ -331,19 +331,20 @@ private int delayedKernelLoadModule(String name, int flags, int uid, SceKernelLM
// some space for the module header itself.
// We allocate the estimated size and free it immediately so that
// we know the load address.
final int partitionId = lmOption != null && lmOption.mpidText != 0 ? lmOption.mpidText : SysMemUserForUser.USER_PARTITION_ID;
final int mpidText = lmOption != null && lmOption.mpidText != 0 ? lmOption.mpidText : SysMemUserForUser.USER_PARTITION_ID;
final int mpidData = lmOption != null && lmOption.mpidData != 0 ? lmOption.mpidData : SysMemUserForUser.USER_PARTITION_ID;
final int allocType = lmOption != null ? lmOption.position : SysMemUserForUser.PSP_SMEM_Low;
final int moduleHeaderSize = 256;

// Load the module in analyze mode to find out its required memory size
SceModule testModule = Loader.getInstance().LoadModule(name, moduleBuffer, MemoryMap.START_USERSPACE, true);
SceModule testModule = Loader.getInstance().LoadModule(name, moduleBuffer, MemoryMap.START_USERSPACE, mpidText, mpidData, true);
moduleBuffer.rewind();
int totalAllocSize = moduleHeaderSize + testModule.loadAddressHigh - testModule.loadAddressLow;
if (log.isDebugEnabled()) {
log.debug(String.format("Module '%s' requires %d bytes memory", name, totalAllocSize));
}

SysMemInfo testInfo = Modules.SysMemUserForUserModule.malloc(partitionId, "ModuleMgr-TestInfo", allocType, totalAllocSize, 0);
SysMemInfo testInfo = Modules.SysMemUserForUserModule.malloc(mpidText, "ModuleMgr-TestInfo", allocType, totalAllocSize, 0);
if (testInfo == null) {
log.error(String.format("Failed module allocation of size 0x%08X for '%s' (maxFreeMemSize=0x%08X)", totalAllocSize, name, Modules.SysMemUserForUserModule.maxFreeMemSize()));
return -1;
Expand All @@ -353,7 +354,7 @@ private int delayedKernelLoadModule(String name, int flags, int uid, SceKernelLM

// Allocate the memory for the memory header itself,
// the space required by the module will be allocated by the Loader.
SysMemInfo moduleInfo = Modules.SysMemUserForUserModule.malloc(partitionId, "ModuleMgr", SysMemUserForUser.PSP_SMEM_Addr, moduleHeaderSize, testBase);
SysMemInfo moduleInfo = Modules.SysMemUserForUserModule.malloc(mpidText, "ModuleMgr", SysMemUserForUser.PSP_SMEM_Addr, moduleHeaderSize, testBase);
if (moduleInfo == null) {
log.error(String.format("Failed module allocation 0x%08X != null for '%s'", testBase, name));
return -1;
Expand All @@ -365,7 +366,7 @@ private int delayedKernelLoadModule(String name, int flags, int uid, SceKernelLM
int moduleBase = moduleInfo.addr;

// Load the module
SceModule module = Loader.getInstance().LoadModule(name, moduleBuffer, moduleBase + moduleHeaderSize, false);
SceModule module = Loader.getInstance().LoadModule(name, moduleBuffer, moduleBase + moduleHeaderSize, mpidText, mpidData, false);
module.load();

if ((module.fileFormat & Loader.FORMAT_SCE) == Loader.FORMAT_SCE ||
Expand Down Expand Up @@ -520,14 +521,19 @@ public int sceKernelStartModule(int uid, int argSize, @CanBeNull TPointer argp,
stackSize = sceModule.module_start_thread_stacksize;
}

int mpidStack = sceModule.mpiddata;
if (smOption != null && smOption.mpidStack > 0) {
mpidStack = smOption.mpidStack;
}

if (smOption != null) {
attribute = smOption.attribute;
}

// Remember the current thread as it can be changed by hleKernelStartThread.
SceKernelThreadInfo currentThread = threadMan.getCurrentThread();

SceKernelThreadInfo thread = threadMan.hleKernelCreateThread("SceModmgrStart", entryAddr, priority, stackSize, attribute, 0);
SceKernelThreadInfo thread = threadMan.hleKernelCreateThread("SceModmgrStart", entryAddr, priority, stackSize, attribute, 0, mpidStack);
// override inherited module id with the new module we are starting
thread.moduleid = sceModule.modid;
// Store the thread exit status into statusAddr when the thread terminates
Expand Down Expand Up @@ -630,6 +636,11 @@ public int sceKernelStopModule(int uid, int argSize, @CanBeNull TPointer argp, @
stackSize = sceModule.module_stop_thread_stacksize;
}

int mpidStack = sceModule.mpiddata;
if (smOption != null && smOption.mpidStack > 0) {
mpidStack = smOption.mpidStack;
}

int attribute = sceModule.module_stop_thread_attr;
if (smOption != null) {
attribute = smOption.attribute;
Expand All @@ -640,7 +651,7 @@ public int sceKernelStopModule(int uid, int argSize, @CanBeNull TPointer argp, @

SceKernelThreadInfo thread = threadMan.hleKernelCreateThread("SceModmgrStop",
sceModule.module_stop_func, priority,
stackSize, attribute, 0);
stackSize, attribute, 0, mpidStack);

thread.moduleid = sceModule.modid;
// Store the thread exit status into statusAddr when the thread terminates
Expand Down Expand Up @@ -695,7 +706,7 @@ public int sceKernelSelfStopUnloadModule(int exitCode, int argSize, @CanBeNull T
// Start the module stop thread function.
thread = threadMan.hleKernelCreateThread("SceModmgrStop",
sceModule.module_stop_func, sceModule.module_stop_thread_priority,
sceModule.module_stop_thread_stacksize, sceModule.module_stop_thread_attr, 0);
sceModule.module_stop_thread_stacksize, sceModule.module_stop_thread_attr, 0, sceModule.mpiddata);
thread.moduleid = sceModule.modid;
// Unload the module when the stop thread will be deleted
thread.unloadModuleAtDeletion = true;
Expand Down Expand Up @@ -730,7 +741,7 @@ public int sceKernelStopUnloadSelfModuleWithStatus(int exitCode, int argSize, @C

thread = threadMan.hleKernelCreateThread("SceModmgrStop",
sceModule.module_stop_func, sceModule.module_stop_thread_priority,
sceModule.module_stop_thread_stacksize, sceModule.module_stop_thread_attr, optionAddr.getAddress());
sceModule.module_stop_thread_stacksize, sceModule.module_stop_thread_attr, optionAddr.getAddress(), sceModule.mpiddata);
thread.moduleid = sceModule.modid;
// Store the thread exit status into statusAddr when the thread terminates
thread.exitStatusAddr = statusAddr;
Expand Down Expand Up @@ -766,7 +777,7 @@ public int sceKernelStopUnloadSelfModule(int argSize, @CanBeNull TPointer argp,
// Start the module stop thread function.
thread = threadMan.hleKernelCreateThread("SceModmgrStop",
sceModule.module_stop_func, sceModule.module_stop_thread_priority,
sceModule.module_stop_thread_stacksize, sceModule.module_stop_thread_attr, optionAddr.getAddress());
sceModule.module_stop_thread_stacksize, sceModule.module_stop_thread_attr, optionAddr.getAddress(), sceModule.mpiddata);
thread.moduleid = sceModule.modid;
// Store the thread exit status into statusAddr when the thread terminates
thread.exitStatusAddr = statusAddr;
Expand Down
14 changes: 8 additions & 6 deletions src/jpcsp/HLE/modules150/ThreadManForUser.java
Expand Up @@ -67,6 +67,8 @@
import static jpcsp.HLE.kernel.types.SceKernelThreadInfo.PSP_WAIT_SEMA;
import static jpcsp.HLE.kernel.types.SceKernelThreadInfo.PSP_WAIT_VPL;
import static jpcsp.HLE.modules.HLEModuleManager.HLESyscallNid;
import static jpcsp.HLE.modules150.SysMemUserForUser.KERNEL_PARTITION_ID;
import static jpcsp.HLE.modules150.SysMemUserForUser.USER_PARTITION_ID;
import static jpcsp.util.Utilities.writeStringZ;

import java.lang.management.ManagementFactory;
Expand Down Expand Up @@ -319,7 +321,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);
currentThread = new SceKernelThreadInfo("root", entry_addr, rootInitPriority, rootStackSize, attr, USER_PARTITION_ID);
currentThread.moduleid = moduleid;
threadMap.put(currentThread.uid, currentThread);

Expand Down Expand Up @@ -458,14 +460,14 @@ private void installIdleThreads() {
// Allocate a stack because interrupts can be processed by the
// idle thread, using its stack.
// The stack is allocated into the reservedMem area.
idle0 = new SceKernelThreadInfo("idle0", IDLE_THREAD_ADDRESS | 0x80000000, 0x7f, 0, PSP_THREAD_ATTR_KERNEL);
idle0 = new SceKernelThreadInfo("idle0", IDLE_THREAD_ADDRESS | 0x80000000, 0x7f, 0, PSP_THREAD_ATTR_KERNEL, KERNEL_PARTITION_ID);
idle0.setSystemStack(reservedMem, 0x2000);
idle0.reset();
idle0.exitStatus = ERROR_KERNEL_THREAD_IS_NOT_DORMANT;
threadMap.put(idle0.uid, idle0);
hleChangeThreadState(idle0, PSP_THREAD_READY);

idle1 = new SceKernelThreadInfo("idle1", IDLE_THREAD_ADDRESS | 0x80000000, 0x7f, 0, PSP_THREAD_ATTR_KERNEL);
idle1 = new SceKernelThreadInfo("idle1", IDLE_THREAD_ADDRESS | 0x80000000, 0x7f, 0, PSP_THREAD_ATTR_KERNEL, KERNEL_PARTITION_ID);
idle1.setSystemStack(reservedMem + 0x2000, 0x2000);
idle1.reset();
idle1.exitStatus = ERROR_KERNEL_THREAD_IS_NOT_DORMANT;
Expand Down Expand Up @@ -1728,14 +1730,14 @@ public int checkPartitionID(int id) {
}

public SceKernelThreadInfo hleKernelCreateThread(String name, int entry_addr,
int initPriority, int stackSize, int attr, int option_addr) {
int initPriority, int stackSize, int attr, int option_addr, int mpidStack) {

if (option_addr != 0) {
Modules.log.warn("hleKernelCreateThread unhandled SceKernelThreadOptParam: " +
"option_addr=0x" + Integer.toHexString(option_addr));
}

SceKernelThreadInfo thread = new SceKernelThreadInfo(name, entry_addr, initPriority, stackSize, attr);
SceKernelThreadInfo thread = new SceKernelThreadInfo(name, entry_addr, initPriority, stackSize, attr, mpidStack);
threadMap.put(thread.uid, thread);

// inherit module id
Expand Down Expand Up @@ -3134,7 +3136,7 @@ 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);
SceKernelThreadInfo thread = hleKernelCreateThread(name, entry_addr, initPriority, stackSize, attr, option_addr, USER_PARTITION_ID);

if (thread.stackSize > 0 && thread.getStackAddr() == 0) {
log.warn("sceKernelCreateThread not enough memory to create the stack");
Expand Down
2 changes: 1 addition & 1 deletion src/jpcsp/HLE/modules150/sceNetAdhocctl.java
Expand Up @@ -588,7 +588,7 @@ public int sceNetAdhocctlInit(int stackSize, int priority, @CanBeNull TPointer p
doScan = false;
doDisconnect = false;
ThreadManForUser threadMan = Modules.ThreadManForUserModule;
adhocctlThread = threadMan.hleKernelCreateThread("SceNetAdhocctl", ThreadManForUser.NET_ADHOC_CTL_LOOP_ADDRESS, priority, stackSize, 0, 0);
adhocctlThread = threadMan.hleKernelCreateThread("SceNetAdhocctl", ThreadManForUser.NET_ADHOC_CTL_LOOP_ADDRESS, priority, stackSize, 0, 0, SysMemUserForUser.USER_PARTITION_ID);
threadMan.hleKernelStartThread(adhocctlThread, 0, 0, adhocctlThread.gpReg_addr);

networkAdapter.sceNetAdhocctlInit();
Expand Down
2 changes: 1 addition & 1 deletion src/jpcsp/HLE/modules150/sceNetApctl.java
Expand Up @@ -401,7 +401,7 @@ public int sceNetApctlInit(int stackSize, int initPriority) {
ThreadManForUser threadMan = Modules.ThreadManForUserModule;
sceNetApctlThread = threadMan.hleKernelCreateThread("SceNetApctl",
ThreadManForUser.NET_APCTL_LOOP_ADDRESS, initPriority, stackSize,
threadMan.getCurrentThread().attr, 0);
threadMan.getCurrentThread().attr, 0, SysMemUserForUser.USER_PARTITION_ID);
sceNetApctlThreadTerminate = false;
threadMan.hleKernelStartThread(sceNetApctlThread, 0, 0, sceNetApctlThread.gpReg_addr);
}
Expand Down
2 changes: 1 addition & 1 deletion src/jpcsp/HLE/modules150/sceUtility.java
Expand Up @@ -497,7 +497,7 @@ public int executeShutdownStart() {
status = PSP_UTILITY_DIALOG_STATUS_FINISHED;

// Execute the shutdown thread, it will set the status to 0.
SceKernelThreadInfo shutdownThread = Modules.ThreadManForUserModule.hleKernelCreateThread("SceUtilityShutdown", ThreadManForUser.UTILITY_LOOP_ADDRESS, params.base.accessThread, 0x800, 0, 0);
SceKernelThreadInfo shutdownThread = Modules.ThreadManForUserModule.hleKernelCreateThread("SceUtilityShutdown", ThreadManForUser.UTILITY_LOOP_ADDRESS, params.base.accessThread, 0x800, 0, 0, SysMemUserForUser.USER_PARTITION_ID);
Modules.ThreadManForUserModule.hleKernelStartThread(shutdownThread, 0, 0, shutdownThread.gpReg_addr);
shutdownThread.cpuContext.setRegister(utilityThreadActionRegister, UTILITY_THREAD_ACTION_SHUTDOWN);

Expand Down
7 changes: 5 additions & 2 deletions src/jpcsp/Loader.java
Expand Up @@ -111,12 +111,14 @@ public void reset() {
* fileFormat member against the FORMAT_* bits.
* Example: (fileFormat & FORMAT_ELF) == FORMAT_ELF
**/
public SceModule LoadModule(String pspfilename, ByteBuffer f, int baseAddress, boolean analyzeOnly) throws IOException {
public SceModule LoadModule(String pspfilename, ByteBuffer f, int baseAddress, int mpidText, int mpidData, boolean analyzeOnly) throws IOException {
SceModule module = new SceModule(false);

int currentOffset = f.position();
module.fileFormat = FORMAT_UNKNOWN;
module.pspfilename = pspfilename;
module.mpidtext = mpidText;
module.mpiddata = mpidData;

// The PSP startup code requires a ":" into the argument passed to the root thread.
// On Linux, there is no ":" in the file name when loading a .pbp file;
Expand Down Expand Up @@ -660,7 +662,8 @@ private void LoadELFReserveMemory(SceModule module) {
int address = module.loadAddressLow & ~(SysMemUserForUser.defaultSizeAlignment - 1); // Round down to match sysmem allocations
int size = module.loadAddressHigh - address;

SysMemInfo info = Modules.SysMemUserForUserModule.malloc(SysMemUserForUser.USER_PARTITION_ID, module.modname, SysMemUserForUser.PSP_SMEM_Addr, size, address);
int partition = module.mpidtext > 0 ? module.mpidtext : SysMemUserForUser.USER_PARTITION_ID;
SysMemInfo info = Modules.SysMemUserForUserModule.malloc(partition, module.modname, SysMemUserForUser.PSP_SMEM_Addr, size, address);
if (info == null || info.addr != address) {
log.warn(String.format("Failed to properly reserve memory consumed by module %s at address 0x%08X, size 0x%X: allocated %s", module.modname, address, size, info));
}
Expand Down
5 changes: 3 additions & 2 deletions src/jpcsp/network/adhoc/MatchingObject.java
Expand Up @@ -44,6 +44,7 @@
import jpcsp.HLE.kernel.types.pspNetMacAddress;
import jpcsp.HLE.modules.ThreadManForUser;
import jpcsp.HLE.modules.sceNetAdhocMatching;
import jpcsp.HLE.modules150.SysMemUserForUser;
import jpcsp.HLE.modules150.sceNetAdhoc;
import jpcsp.hardware.Wlan;
import jpcsp.memory.IMemoryReader;
Expand Down Expand Up @@ -183,14 +184,14 @@ public int start(int evthPri, int evthStack, int inthPri, int inthStack, int opt
if (eventThread == null) {
eventThread = threadMan.hleKernelCreateThread("SceNetAdhocMatchingEvent",
ThreadManForUser.NET_ADHOC_MATCHING_EVENT_LOOP_ADDRESS,
evthPri, evthStack, threadMan.getCurrentThread().attr, 0);
evthPri, evthStack, threadMan.getCurrentThread().attr, 0, SysMemUserForUser.USER_PARTITION_ID);
threadMan.hleKernelStartThread(eventThread, 0, 0, eventThread.gpReg_addr);
eventThread.cpuContext.setRegister(sceNetAdhocMatching.loopThreadRegisterArgument, getId());
}
if (inputThread == null) {
inputThread = threadMan.hleKernelCreateThread("SceNetAdhocMatchingInput",
ThreadManForUser.NET_ADHOC_MATCHING_INPUT_LOOP_ADDRESS,
inthPri, inthStack, threadMan.getCurrentThread().attr, 0);
inthPri, inthStack, threadMan.getCurrentThread().attr, 0, SysMemUserForUser.USER_PARTITION_ID);
threadMan.hleKernelStartThread(inputThread, 0, 0, inputThread.gpReg_addr);
inputThread.cpuContext.setRegister(sceNetAdhocMatching.loopThreadRegisterArgument, getId());
}
Expand Down

0 comments on commit 5c90f1b

Please sign in to comment.