User Thread from Kernel Bootstrap Crash?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Jabberwocky
Posts: 43
Joined: Wed Aug 03, 2005 6:58 pm

User Thread from Kernel Bootstrap Crash?

Post by Jabberwocky »

I'm having trouble starting and running a user mode thread from a kernel mode bootstrap (not using the normal crt0). Can anyone tell me why this does not work -- it crashes when sceKernelStartThread is called):

Code: Select all

int _main(int args, void *argp)
{
	return 0;
}

int _start(int args, void *argp)
{
	int (*_main_func)(SceSize args, void *argp) = _main;
	_main_func = (void *) ((unsigned int) _main_func & 0x7fffffff);

	int thid = sceKernelCreateThread(	"user_main",
										_main_func, 
										32,
										4096,
										PSP_THREAD_ATTR_USER,
										(void*) 0);


	sceKernelStartThread(thid, args, argp);

	return 0;
}
I am linking with *ForKernel versions of all the appropriate libraries, and I really can't understand why it isn't working... I seem to be able to create and start a kernel mode thread ok (using 0 instead of PSP_THREAD_ATTR_USER and not anding the top bits of the address), but not user.

:EDIT: Examining the thread before starting it, the only thing I can see which might be a bit dodgy is that the GP value for the thread is in kernel space, the rest looks good. What the hell is the GP anyway?!
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

Post by Fanjita »

$gp is used by some code as a sort of pointer to the global data area - I see quite a lot of generated code where most of the data is accessed relative to $gp, e.g.

Code: Select all

lw  $t0, 1234($gp) 
You can pretty easily check your disassembly to see if your code is using $gp. I'd also expect that you'll see your thread crashing later, rather than sooner, if this is the culprit - you could test with a

Code: Select all

while(1) sceKernelDelayThread(xxxX);
loop in your thread as the first instruction - this shouldn't crash if $gp is the problem.

As for fixing it, I don't know the correct way, but you could probably kludge it by determining the new address of the first item in the $gp area, and assigning that to $gp with some inline assembly - maybe useful as a quick test.
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
Jabberwocky
Posts: 43
Joined: Wed Aug 03, 2005 6:58 pm

Post by Jabberwocky »

Ah, ok, I thought gp may have been some kind of base pointer. This doesn't explain my crash, then. I have tried a while(1) in the thread, and it still crashes. It's as if actually calling the thread is what is causing the crash, but the address looks OK for user mode code (ie. top nibble clear).

Very strange -- I'm going to just try and write the code in kernel mode instead as I can create kernel threads, but this is going to bug me! It should work...

Thanks for the info.
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Err what crash code are you getting (i.e. install an exception handler)? Considering some of your other posts you made and the fact that you say gp is a kernel address it would almost seem that you are trying to load a kernel mode prx and create a user mode thread in it, that wouldn't work.

If you must create a user thread from a kernel module then the best (nay only) way to do it is to malloc a block of user memory, copy in your code and then create a user mode thread at that address.

Alternatively...
Jabberwocky
Posts: 43
Joined: Wed Aug 03, 2005 6:58 pm

Post by Jabberwocky »

Ah, ok. Yes, I am using a kernel mode PRX, but assumed you could create a user mode thread from this as you can a kernel mode ELF. As has been mentioned before, there isn't any difference between an ELF and PRX, so I didn't see any reason why this wouldn't work.

However, I now realise that as the PRX is residing in kernel space memory (which the ELF isn't), and hence the problem.
Post Reply