Fuente:
http://forums.ps2dev.org/viewtopic.php?t=8333&postdays=0&postorder=asc&start=0
Disregard my previous post, I got it working now.
I am working on getting the second thread running, which I now have achieved (plus some other minor optimisations).
Here is my code in progress in case anyone else wants the second thread. (This is just the boot code, you need to provide your own secondary_main, etc.
Things to note:
1. Secondary thread needs to be brought up in lock synch with the primary thread.
2. Secondary thread needs to have its mmu enabled, but not to the same extent as the primary, because it seems to share a lot of the resources. The setup_slb function needs to also be called by the secondary but the secondary doesnt need the rest of the mmu_init code.
3. Init your drivers in the main thread before running app code on the secondary. The __release_secondary function is used to control that.
4. There is some untested spinlock code in there which I will use for inter-thread resource management in my app.
5. Make sure in C, that any variables shared by both threads are marked volatile, and that you have appropriate sharing methodologies in place.
Anyway, here is my version of start.S :
Code:
.section .text.vectors,"ax",@progbits
#include "asm.h"
.extern .exception_handler
.extern .mmu_init
.extern .setup_slb
.extern .main
/* Constants for use with the Secondary hold semaphore */
#define SECONDARY_HOLD_AT_RESET 0
#define SECONDARY_HOLD_KBOOT_INIT_OK 1
#define SECONDARY_HOLD_RESET_INIT_OK 2
#define SECONDARY_HOLD_DRIVER_INIT_OK 3
.global Reset_Vector, ._mmu_off, __mmu_off, __release_secondary, __CPU_THREAD_ID,
/****** MAIN THREAD KBOOT ENTRY * 0x00000000 ************************/
/* This is the entry point of the main PPE thread
when we're started from kboot.
r3 contains a pointer to the "device tree"
r4 contains the address to which the program was loaded
(When started from kboot, the program isn't loaded to
address 0, but to an arbitrary address. The first
256 bytes are copied to 0, but the rest needs to be
moved by the program itself)
r5 contains 0
*/
Kboot_primary_start:
bl .__mmu_off /* just in case */
li r3,0 /* Target address in r3 */
/* The source address is already in r4 */
LOAD_REG_IMMEDIATE32(r5,_edata) /* Address to copy to (end of the program, set by linker) */
/* Program needs to be less than 4GB, */
/* which is no problem, as we only have 4MB of flash to play with */
li r6,0x100 /* Start offset, the first 0x100 */
/* bytes were copied earlier. */
copy_and_flush:
addi r5,r5,-8
addi r6,r6,-8
4: li r0,16 /* Use the least common */
/* denominator cache line */
/* size. This results in */
/* extra cache line flushes */
/* but operation is correct. */
mtctr r0 /* put # words/line in ctr */
3: addi r6,r6,8 /* copy a cache line */
ldx r0,r6,r4
stdx r0,r6,r3
bdnz 3b
dcbst r6,r3 /* write it to memory */
sync
icbi r6,r3 /* flush the icache line */
cmpld 0,r6,r5
blt 4b
sync
li r3,__SecondaryHold_Semaphore@l/* Secondary KBoot hold flag */
li r4,SECONDARY_HOLD_KBOOT_INIT_OK
/* Flag to allow secondary to run */
stw r4,0(r3) /* Write Secondary wait flag, copied now, so go */
b start_primary
/****** SECONDARY THREAD KBOOT ENTRY * Anywhere + 0x00000060 ***************************/
/* This is the entry point of the PPE slaves (of which
there is exactly one in the case of the PS3) when
we're started from kboot.
r3 holds the number of the CPU (= 1) */
. = 0x60
Kboot_secondary_start:
bl .__mmu_off /* just in case */
Kboot_secondary_wait:
lwz r3,__SecondaryHold_Semaphore(0)
/* Read Secondary wait flag */
and. r3,r3,r3 /* Check if we can start yet */
beq Kboot_secondary_wait /* No, so just wait until not = 0. */
b start_secondary /* Start Secondary like at reset */
/* Holds the secondary thread paused until a sync point */
/* is reached by the main thread, allowing it to continue. */
/* 0 = Hold at reset */
/* 1 = Kboot primary init phase complete */
/* 2 = Primary Reset configuration complete */
/* 3 = Primary driver initialisation complete */
__SecondaryHold_Semaphore:
.long SECONDARY_HOLD_AT_RESET
/****** _mmu_off function. We put it here, because we need it when booted by kboot. ***************************/
.__mmu_off:
mfmsr r3
andi. r0,r3,MSR_IR|MSR_DR
beqlr
mflr r4
andc r3,r3,r0
mtspr SRR0,r4
mtspr SRR1,r3
sync
rfid
b . /* prevent speculative execution */
/****** OTHEROS Entry Point (Reset Vector) * 0x00000100 ***************************/
/* This is the entry point of both the main and slave
PPE threads when we're started from GameOS.
r3 appears to hold the CPU number, but we'll check nevertheless */
. = 0x100
Reset_Vector:
bl .__mmu_off /* just in case */
bl __CPU_THREAD_ID
beq start_primary
b start_secondary
__CPU_THREAD_ID:
mfspr r3, CTRLF
cntlzw. r3, r3 /* r3 is now CPU number 0=master, 1=slave */
blr
/****** EXCEPTION AND IRQ VECTORS * 0x00000200 - 0x00000F00 ***************************/
/* Exception and interrupt vectors */
#define GENERAL_EXCEPTION_HANDLER(vec) \
/* This handler does not return, so trashing registers is ok */ \
mtspr SPRG1, r3; \
li r3,vec; \
mfspr r4, SRR0; \
mfspr r5, SRR1; \
LOAD_REG_IMMEDIATE64(r1,__primary_stack_end); \
li r0,0; \
stdu r0,-STACK_FRAME_OVERHEAD(r1); \
LOAD_REG_IMMEDIATE64(r2,__toc_start); \
addi r2,r2,0x4000; \
addi r2,r2,0x4000; \
bl .__mmu_on; \
bl .exception_handler; \
1: b 1b;
. = 0x200 /* Machine check */
GENERAL_EXCEPTION_HANDLER(0x200)
. = 0x300 /* DSI */
GENERAL_EXCEPTION_HANDLER(0x300)
. = 0x380 /* Data segment */
GENERAL_EXCEPTION_HANDLER(0x380)
. = 0x400 /* ISI */
GENERAL_EXCEPTION_HANDLER(0x400)
. = 0x480 /* Instruction segment */
GENERAL_EXCEPTION_HANDLER(0x480)
. = 0x500 /* External interrupt */
GENERAL_EXCEPTION_HANDLER(0x500)
. = 0x600 /* Alignment */
GENERAL_EXCEPTION_HANDLER(0x600)
. = 0x700 /* Program */
GENERAL_EXCEPTION_HANDLER(0x700)
. = 0x800 /* Floating point unavailable */
GENERAL_EXCEPTION_HANDLER(0x800)
. = 0x900 /* Decrementer */
GENERAL_EXCEPTION_HANDLER(0x900)
. = 0xa00 /* Reserved 1 */
GENERAL_EXCEPTION_HANDLER(0xA00)
. = 0xb00 /* Reserved 2 */
GENERAL_EXCEPTION_HANDLER(0xB00)
. = 0xc00 /* System call */
GENERAL_EXCEPTION_HANDLER(0xC00)
. = 0xd00 /* Trace */
GENERAL_EXCEPTION_HANDLER(0xD00)
. = 0xe00 /* Reserved */
GENERAL_EXCEPTION_HANDLER(0xE00)
. = 0xf00 /* Performance monitor */
GENERAL_EXCEPTION_HANDLER(0xF00)
/****** Primary Thread Entry point ***************************/
. = 0x1000 /* Performance monitor */
start_primary:
/* Clear out the BSS */
LOAD_REG_IMMEDIATE64(r11,__bss_stop)
LOAD_REG_IMMEDIATE64(r8,__bss_start)
sub r11,r11,r8 /* bss size */
addi r11,r11,7 /* round up to an even double word */
rldicl. r11,r11,61,3 /* shift right by 3 */
beq 4f
addi r8,r8,-8
li r0,0
mtctr r11 /* zero this many doublewords */
3: stdu r0,8(r8)
bdnz 3b
4:
/* Setup stack */
LOAD_REG_IMMEDIATE64(r1,__primary_stack_end)
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
/* Setup TOC */
LOAD_REG_IMMEDIATE64(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
/* Create and activate address space */
bl .mmu_init
bl .__mmu_on
li r3,SECONDARY_HOLD_RESET_INIT_OK
/* Flag to allow secondary to run */
stw r3,__SecondaryHold_Semaphore(0) /* Write Secondary wait flag, copied now, so go */
/* And we're off... */
bl .main /* If this returns */
b .reboot /* we are dead. */
start_secondary:
/* Setup stack */
LOAD_REG_IMMEDIATE64(r1,__secondary_stack_end)
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
/* Setup TOC */
LOAD_REG_IMMEDIATE64(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
mmu_secondary_wait:
lwz r3,__SecondaryHold_Semaphore(0)
/* Read Secondary wait flag */
cmplwi r3,SECONDARY_HOLD_RESET_INIT_OK
/* Check if we can start yet */
blt mmu_secondary_wait /* No, so just wait until mmu set up. */
/* Activate address space created by primary */
bl .setup_slb
bl .__mmu_on
driver_secondary_wait:
lwz r4,0(r3) /* Read Secondary wait flag */
cmplwi r4,SECONDARY_HOLD_DRIVER_INIT_OK
/* Check if we can start yet */
blt driver_secondary_wait /* No, so just wait until mmu set up. */
bl .secondary_main /* If this returns */
b .reboot /* we are dead. */
.__mmu_on:
LOAD_REG_IMMEDIATE64(r0, MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF | MSR_SF)
mtspr SRR1,r0
mflr r0
mtspr SRR0,r0
sync
rfid
b . /* prevent speculative execution */
__release_secondary:
li r3,SECONDARY_HOLD_DRIVER_INIT_OK
/* Flag to allow secondary to run */
stw r3,__SecondaryHold_Semaphore(0) /* Write Secondary wait flag, copied now, so go */
blr
.__raw_spinlock: /* R3 = Address of spinlock variable (32 bit variable) */
/* R4 = Spinlock Token (32 bits are significant) (must != 0) */
lwz r5,0(r3) /* Read Spinlock */
cmplwi r5,0 /* Check if spinlock in use. */
bne .__raw_spinlock /* Spinlock != 0, so spin. */
stw r4,0(r3) /* Write Spinlock with Token */
lwz r5,0(r3) /* Read Spinlock */
cmplw r5,r4 /* Check if spinlock obtained. */
bne .__raw_spinlock /* Spinlock != Token, so spin */
blr /* Got spinlock, so return - resource is ours. */
.section ".opd","aw"
__mmu_off:
.llong .__mmu_off
.llong .TOC.@tocbase
.llong 0
.section ".bss"
.align 3
__primary_stack:
.space 65536
__primary_stack_end:
__secondary_stack:
.space 65536
__secondary_stack_end:
And for completeness a copy of my asm.h:
Code:
#ifndef __ASM_H__
#define __ASM_H__
#define LOAD_REG_IMMEDIATE64(reg,expr) \
lis reg,(expr)@highest; \
ori reg,reg,(expr)@higher; \
rldicr reg,reg,32,31; \
oris reg,reg,(expr)@h; \
ori reg,reg,(expr)@l;
#define LOAD_REG_IMMEDIATE32(reg,expr) \
lis reg,(expr)@h; \
ori reg,reg,(expr)@l; \
#define STACK_FRAME_OVERHEAD 112 /* minimum ppc64 stack frame */
/* MSR bits */
#define MSR_SF (1<<63) /* Enable 64 bit mode */
#define MSR_ISF (1<<61) /* Interrupt 64b mode valid on 630 */
#define MSR_HV (1<<60) /* Hypervisor state */
#define MSR_VEC (1<<25) /* Enable AltiVec */
#define MSR_POW (1<<18) /* Enable Power Management */
#define MSR_WE (1<<18) /* Wait State Enable */
#define MSR_TGPR (1<<17) /* TLB Update registers in use */
#define MSR_CE (1<<17) /* Critical Interrupt Enable */
#define MSR_ILE (1<<16) /* Interrupt Little Endian */
#define MSR_EE (1<<15) /* External Interrupt Enable */
#define MSR_PR (1<<14) /* Problem State / Privilege Level */
#define MSR_FP (1<<13) /* Floating Point enable */
#define MSR_ME (1<<12) /* Machine Check Enable */
#define MSR_FE0 (1<<11) /* Floating Exception mode 0 */
#define MSR_SE (1<<10) /* Single Step */
#define MSR_BE (1<<9) /* Branch Trace */
#define MSR_DE (1<<9) /* Debug Exception Enable */
#define MSR_FE1 (1<<8) /* Floating Exception mode 1 */
#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
#define MSR_IR (1<<5) /* Instruction Relocate */
#define MSR_DR (1<<4) /* Data Relocate */
#define MSR_PE (1<<3) /* Protection Enable */
#define MSR_PX (1<<2) /* Protection Exclusive Mode */
#define MSR_PMM (1<<2) /* Performance monitor */
#define MSR_RI (1<<1) /* Recoverable Exception */
#define MSR_LE (1<<0) /* Little Endian */
/* SPRs */
#define SRR0 0x01A /* Save/Restore Register 0 */
#define SRR1 0x01B /* Save/Restore Register 1 */
#define CTRLF 0x088
#define SPRG0 0x110
#define SPRG1 0x111
#define SPRG2 0x112
#define SPRG3 0x113
#endif
PD: Esto sí que parece un avance, porque si al pavo le ha dado por meter este pedazo de texto del código y ha ido cambiando palabras para poner PS3 es que está chaladísimo. Lo dicho, el tio este, Strontium Dog, parece que ha encontrado algo grande.
Aquí el archivo demo que sale en ese foro, publicado por mc:
http://mc.pp.se/ps3/otheros_demo_1.0.zip
Mi duda ahora es, mc y Strontium Dog trabajan juntos, son avances distintos...ki lo sa