| View previous topic :: View next topic |
| Author |
Message |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Wed Dec 06, 2006 11:24 am Post subject: SC/ME processors : memory mappings |
|
|
SC and ME have the same revision code (PRId) "31040125", so we can expect a lot of similarities between them indeed.
| Code: |
COP0 registers :
[ SC ] [ ME ]
15 - 31040125 - 31040125 - PRId
16 - 00000480 - 00000480 - Config
|
I suspect both CPUs using a FM (Fix Mapped) MMU which could explain the current mapping and the lack of a TLB MMU.
COP0.Config is the same so they almost share the same memory mapping :
0x00000000-0x3fffffff : KUSEG0 -> kernel/user mapped.
0x40000000-0x7fffffff : KUSEG1 -> kernel/user mapped.
0x80000000-0x9fffffff : KSEG0 -> kernel unmapped cached
0xA0000000-0xbfffffff : KSEG1 -> kernel unmapped uncached
SC Processor :
| Code: |
0x04000000 - 2MB : cached VRAM
0x08000000 - 32MB : cached main memory
0x44000000 - 2MB : uncached VRAM
0x48000000 - 32MB : uncached main memory
0x84000000 - 2MB : cached VRAM
0x88000000 - 32MB : cached main memory
0xA4000000 - 2MB : uncached VRAM
0xA8000000 - 32MB : uncached main memory
|
ME processor :
| Code: |
0x04000000 - 2MB : cached ???, mirror of 0x84000000
0x08000000 - 32MB : cached main memory, mirror of 0x88000000
0x44000000 - 2MB : uncached ???, mirror of 0xA4000000
0x48000000 - 32MB : uncached main memory, mirror of 0xA8000000
0x80000000 - 2MB : cached eDRAM
0x84000000 - 2MB : cached ??? (can modify contents only in cache)
0x88000000 - 32MB : cached main memory
0xA0000000 - 2MB : uncached eDRAM
0xA4000000 - 2MB : uncached ??? (unmodifiable contents)
0xA8000000 - 32MB : uncached main memory
|
ME processor has a weird memory starting at 0x?4000000. I dunno if it is for VRAM. If so, we probably need to enable its access through an unknown setting of a controller.
Last edited by hlide on Thu Dec 07, 2006 8:24 am; edited 3 times in total |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Thu Dec 07, 2006 7:29 am Post subject: |
|
|
if someone has more details about how to raise an interrupt from ME into SC and vice versa, I'm very interested.
Anyway, it would be interesting to check if ME processor can use the same exceptions than SC processor. They are necessary for creating a small kernel for ME processor that would be more robuste that the actual code we have. If we can figure the way how to signal the other processor to give an order or a result, it would be cool.
EDIT : I don't mean running SC exceptions code into ME processor but to have the same way to handle the exceptions with ME processor |
|
| Back to top |
|
 |
TyRaNiD
Joined: 18 Jan 2004 Posts: 918
|
Posted: Thu Dec 07, 2006 7:53 am Post subject: |
|
|
| Code: | asm("sync\n");
_sw(1, 0xBC100044);
asm("sync\n");
|
Should raise interrupt 31 on the ME and vice versa. |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Thu Dec 07, 2006 8:21 am Post subject: |
|
|
| TyRaNiD wrote: | | Code: | asm("sync\n");
_sw(1, 0xBC100044);
asm("sync\n");
|
Should raise interrupt 31 on the ME and vice versa. |
cool !!!! thanx very much !
EDIT: it doesn't seem to work. I probably miss something :/
According to yad4psp :
interrupt 31 : SYS_REG ME Codec. So this is not an exception but an interrupt. Maybe this interrupt is by default a "nop" so it may explain why i cannot receive anything (or this interrupt is masked ?) |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Thu Dec 07, 2006 9:19 am Post subject: |
|
|
hummm SYSREG_driver (FW 1.5) gives us :
| Code: |
// sceSysregInterruptToOther ???
int 880790ac(void)
{
_sync();
_writew(1, 0xbc100044);
_sync();
return 0;
}
// sceSysregSemaTryLock ???
int 880790cc(void)
{
_sync();
v0 = _mfc0(22); // CPUId (0 -> SC / 1 -> ME)
a2 = v0 + 1; // 1 -> SC / 2 -> ME
_writew(a2, 0xbc100048); // try to acquire semaphore
a3 = _readw(0xbc100048) & 3; // who owns semaphore ?
return -((a2 ^ a3) != 0); // 0 if successful or -1 if not
}
// sceSysregSemaUnlock ???
void 880790fc(void)
{
_sync();
_writew(0, 0xbc100048); // owner releases semaphore
_sync();
return;
}
|
Last edited by hlide on Thu Dec 07, 2006 11:48 pm; edited 2 times in total |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Thu Dec 07, 2006 9:43 am Post subject: |
|
|
| We appreciate the work you're doing on the ME, hlide. This could really improve a variety of programs, being able to run some things on the ME. |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Fri Dec 08, 2006 7:13 pm Post subject: |
|
|
ok, semaphore is working. I am able to sync SC and ME with 0xBC100048.
now, i want to use int 31. Running PSPINSIDE, i can see it is activated and calls a function which sets an event flag.
pspsdk really lacks of functions on interrupts. I'm wondering how to proceed. I can see several interesting functions in http://pspdev.ofcode.com/api2.0/index.php?type=2&id=34 but i have no detail about them (i'm under FW1.5).
There could be one solution, to access the interrupt table and set our own interrupt for int 31... but it is very dirty. :/
EDIT: talking about semaphore, it is much more like a mutex indeed. |
|
| Back to top |
|
 |
rapso
Joined: 28 Mar 2005 Posts: 147
|
Posted: Fri Dec 08, 2006 8:25 pm Post subject: Re: SC/ME processors : memory mappings |
|
|
| hlide wrote: | | ME processor has a weird memory starting at 0x?4000000. I dunno if it is for VRAM. If so, we probably need to enable its access through an unknown setting of a controller. | afaik, before the psp was released, there were rumors talkin about 4MB VRam. maybe it's the upper or lower 2MB of that VRam, so maybe u cannot access it by the main cpu, but maybe set it as frontbuffer/display?
[edit]
I searched it and found the description on this side: http://www.hartware.de/review_492_3.html
| Quote: |
Neben den 32 MB besitzen die CPUs, wie schon gesagt, rund 4 MB eDRAM. Diese 4 MB verteilen sich auf die Media Engine und den Grafikkern. | except of the 32MB main memory, 4MB eDRAM are available, splited to the ME and GU.
| Quote: |
Wie bei der Haupt-CPU ist der Takt der Media Engine von 1 bis 333 MHz regelbar. Diese verfügt aber über 2 MB der insgesamt 4 MB eDRAM. Diese 2 MB hängen dabei an einem Bus, der mit der halben Taktfrequenz der Media Engine läuft, das heißt maximal 166 Mhz. |
As the main CPU, the ME can be set from 1 to 333MHz, it has access to 2MB of the whole 4MB eDRAM. Those 2MB are running with the same speed as the bus of the ME, 166MHz.
[/edit]
maybe it's just for movie playing, but maybe we could even use it as 2MB additional texture memory (maybe even motion-textures) |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Sat Dec 09, 2006 3:07 am Post subject: |
|
|
I managed to set my own exceptions but i would like to be able to use the one already provided if possible.
This is the function set by default into cop0 status register EBASE :
| Code: |
ctc0 $v0, $4
ctc0 $v1, $5
lui $v1, 0xBC200000
lui $v0, 0x1FF0000
ori $v0, 0x1FF
sw $v0, ($v1)
mfc0 $v0, $13
ctc0 $v0, $3
andi $v0, 0x7C
mfc0 $v1, $14
ctc0 $v1, $0
cfc0 $v1, $8
add $v1, $v0
lw $v1, ($v1)
mfc0 $v0, $12
jr $v1
ctc0 $v0, $2
|
I cannot find what 0xBC200000 is (not documented in yad4psp). Any idea ? is it something usable only for ME ?
cop0 control register 8 doesn't seem to contain a valid address on a 32-entry exception table, but we can set ours here. |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Sat Dec 09, 2006 9:27 am Post subject: |
|
|
okay, now SC processor can display exception details coming from ME using 'pspDebugDumpException'. At least it should be a help to develop on ME processor.
I'm still clueless about how to deroute int 31 in SC processor so ME can signal an exception for instance. :/
Next task : SC signaling ME via int 31.
I'll plan to release a ME library which should allow ME and SC to communicate to each other and catch ME exceptions too when evrything is okay.
Maybe a small RPC-like mechanism can be added to allow ME processor to "borrow" SC ressources. |
|
| Back to top |
|
 |
Chrighton
Joined: 15 Jun 2005 Posts: 58
|
Posted: Sat Dec 09, 2006 12:00 pm Post subject: |
|
|
| Nice work, hlide. Thanks for keeping us up to date on your findings. |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Mon Dec 11, 2006 4:17 am Post subject: |
|
|
since i'm unsuccessful with int 31, i tried to discover much about SYSREG functions :
| Code: |
int sceSysregIntrInit(void)
{
sceKernelRegisterIntrHandler(31, 1, 0x88080118, 0, 0x88089DF0);
sceKernelEnableIntr(a0 = 31);
return 0;
}
NOTE : 0x88080118 seems to be in the .text section of module sceDMACPLUS_Driver.
int sceSysregIntrEnd(void)
{
sceKernelReleaseIntrHandler(31);
return 0;
}
int sceSysregInterruptToOther(void)
{
_sync();
_sw(0xbc100044) = 1;
_sync();
return 0;
}
int sceSysregSemaTryLock(void)
{
_sync();
v0 = _mfc0(22); // CPUId (0 -> SC / 1 -> ME)
a2 = v0 + 1; // 1 -> SC / 2 -> ME
_sw(0xbc100048) = a2; // try to acquire semaphore
a3 = _lw(0xbc100048) & 3; // who owns semaphore ?
return -(a2 != a3); // 0 if successful or -1 if not
}
void sceSysregSemaUnlock(void)
{
_sync();
_sw(0xbc100048) = 0; // owner releases semaphore
_sync();
return;
}
bool sceSysregEnableIntr(int no)
{
if (no > 31) return 0x80000102;
v0 = sceKernelCpuSuspendIntr();
t0 = _lw(0x880089E04);
_sw(0x880089E04) = t0 | (1 << no)
sceKernelCpuResumeIntr(v0);
return (t0 >> no) & 1;
}
bool sceSysregDisableIntr(int no)
{
if (no > 31) return 0x80000102;
v0 = sceKernelCpuSuspendIntr();
t0 = _lw(0x880089E04);
_sw(0x880089E04) = t0 & ~(1 << no)
sceKernelCpuResumeIntr(v0);
return (t0 >> no) & 1;
}
int sceSysregRequestIntr(int cpu, int no)
{
if ((no > 31) || (cpu > 1)) return 0x80000102;
s0 = cpu;
s1 = no;
while (sceSysregSemaTryLock() < 0);
t0 = 0xBFC00400 + (cpu << 2);
_sw(t0) = _lw(t0) | (1 << no);
sceSysregSemaUnlock();
if (_mfc0(22) != cpu) sceSysregInterruptToOther();
return 0;
}
|
those functions are definitely weird... it seems to imply the interrupt can be "shared" between SC and ME. SYSREG seems to be used in such way that ME and SC can know what is in charge of such interrupt. I guess we should have a look on meAudio or meCodec instead. |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Mon Dec 11, 2006 4:35 am Post subject: |
|
|
Well, it makes sense that they would share the int. Think about how you would communicate with one int and one semaphore...
Both CPUs watch the same int.
CPU 1 decides it needs CPU 2 to do something for it.
CPU 1 tries to acquire the semaphore and is successful.
CPU 1 generates the int.
CPU 1's int handler sees it has the semaphore and exits.
CPU 2's int handler sees that CPU 1 has the semaphore and does what is needed to respond to CPU 1.
CPU 1 sees CPU 2 responding and releases the semaphore.
CPU 2 finishes and tries for the semaphore and is (maybe eventually) successful.
CPU 2 generates the int to show it finished.
CPU 2's int handler sees it has the semaphore and exits.
CPU 1's int handler sees CPU 2 has the semaphore and does what is needed to acknowledge CPU 2 is done.
CPU 2 releases the semaphore.
Something like that... |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Mon Dec 11, 2006 5:39 am Post subject: |
|
|
I prefer to say mutex instead of semaphore, for mutex is more appropriate according to what I saw. In fact, there are uses as "enter_critical_session" and "leave_critical_session".
This mutex protects access to 0xBFC00400/0xBFC00404 (i don't think they are part of interrupt controller but a "shared" data between SC and ME) and doesn't last very long indeed.
This mutex is not held when generating an int.
Those functions don't act really on interrupt controller. So I suppose you cannot use them solely but probably must be used along with functions having a real effect on interrupt controler. |
|
| Back to top |
|
 |
|