OtherOS demo program
OtherOS demo program
Well, for those of you who would like to program the PS3 without messing
around with Linux, I have now completed a demo app that runs directly
under the hypervisor. I.e. no linux needed, not even kboot.
Source and binaries here
It demonstrates graphics rendering with the CPU (directly to DDR memory)
and multibuffering, as well as some needed system management (set
video mode, reboot etc.)
Enjoy.
// Marcus
around with Linux, I have now completed a demo app that runs directly
under the hypervisor. I.e. no linux needed, not even kboot.
Source and binaries here
It demonstrates graphics rendering with the CPU (directly to DDR memory)
and multibuffering, as well as some needed system management (set
video mode, reboot etc.)
Enjoy.
// Marcus
Flying at a high speed
Having the courage
Getting over crisis
I rescue the people
Having the courage
Getting over crisis
I rescue the people
- StrontiumDog
- Posts: 55
- Joined: Wed Jun 01, 2005 1:41 pm
- Location: Somewhere in the South Pacific
Re: OtherOS demo program
awesome. really good job!mc wrote: ...
Enjoy.
// Marcus
I compiled it on Ubuntu/PPC, but any platform should be ok as longps2devman wrote:Do you think a toolchain under cygwin to compile it is possible?
If not, what is the suggested best platform for compilation?
as you have a cross compiler and adjust CC accordingly.
Flying at a high speed
Having the courage
Getting over crisis
I rescue the people
Having the courage
Getting over crisis
I rescue the people
-
- Posts: 2
- Joined: Mon Apr 17, 2006 8:26 am
The demo will not touch the contents of your harddrive. You'll need to
reinstall kboot in the flash afterwards though (using Install OtherOS in the
menu). Or you can run the elf from kboot if you just want to check it out
and not remove kboot from the flash even temporarily.
No, this is not a way to run PS2 homebrew. For starters, PS2 homebrew
is MIPS code, not PPC...
reinstall kboot in the flash afterwards though (using Install OtherOS in the
menu). Or you can run the elf from kboot if you just want to check it out
and not remove kboot from the flash even temporarily.
No, this is not a way to run PS2 homebrew. For starters, PS2 homebrew
is MIPS code, not PPC...
Flying at a high speed
Having the courage
Getting over crisis
I rescue the people
Having the courage
Getting over crisis
I rescue the people
- StrontiumDog
- Posts: 55
- Joined: Wed Jun 01, 2005 1:41 pm
- Location: Somewhere in the South Pacific
I cant compilate it...
Bytes and thanks
What i need to install ? or what is the problem ?manuel@manuel-laptop:~/Desktop/source$ make
gcc -O -m64 -mregnames -mfull-toc -G0 -ffreestanding -fno-stack-protector -c -o start.o start.S
gcc: unrecognized option '-G0'
cc1: error: unrecognized command line option "-mregnames"
cc1: error: unrecognized command line option "-mfull-toc"
make: *** [start.o] Error 1
Bytes and thanks
Unless manuel-laptop is a PS3, that's not gonna work. Build it on a PS3, or build and use a cross compiler.utech wrote:I cant compilate it...
manuel@manuel-laptop:~/Desktop/source$ make
gcc -O -m64 -mregnames -mfull-toc -G0 -ffreestanding -fno-stack-protector -c -o start.o start.S
gcc: unrecognized option '-G0'
cc1: error: unrecognized command line option "-mregnames"
cc1: error: unrecognized command line option "-mfull-toc"
make: *** [start.o] Error 1
I havent tried this yet, but since the elf is built to run on baremetal (well, bare hypervised metal anyway) you wont be able to run it under linux or kboot - a segfault sounds about right.StrontiumDog wrote:I just tried to run the ELF in your demo and it just segfaults? Any tricks to running that? I am running it under kboot.
I am about to try and install is as an otheros to see what happens.
To launch it from kboot, I assume you have to kexec it, in much the same way that you kexec the 'real' kernel of your distro.
edit: or place it somewhere in /boot of your distro (next to vmlinux) and create a new entry in /etc/kboot.conf which will point to the new elf. Then at the kboot prompt, type the name of that new entry and it should launch that instead of linux. This way you dont have to flash anything, nor mess around directly with the kexec syscall, as the kboot wrapper will do this for you.
Damn, I need a decent signature!
- StrontiumDog
- Posts: 55
- Joined: Wed Jun 01, 2005 1:41 pm
- Location: Somewhere in the South Pacific
- StrontiumDog
- Posts: 55
- Joined: Wed Jun 01, 2005 1:41 pm
- Location: Somewhere in the South Pacific
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 :
And for completeness a copy of my asm.h:
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: Select all
.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:
Code: Select all
#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
Yeah, debugging the startup code is a bitch, especially since it needs toStrontiumDog wrote:Any tips on what you did to debug it? Or did you just Burn and Learn? I can't output debug info to the screen because it isn't even getting that far.
do so much before anything can be seen on the screen.
For the initial development, I used a modified kboot kernel which left
the screen enabled and memory mapped, so I could add early printouts.
After I had something working, I generally put new code _after_ fb_init(),
so I could see what was happening if it crashed, and moved it to the correct
place afterwards. Other than that, it was mainly a process of making small
incremental changes, testing often, and pulling my hair a lot. :-)
Flying at a high speed
Having the courage
Getting over crisis
I rescue the people
Having the courage
Getting over crisis
I rescue the people
Appendix E ("Synchronization Programming Examples") in the ProgrammingStrontiumDog wrote:5. Make sure in C, that any variables shared by both threads are marked volatile, and that you have appropriate sharing methodologies in place.
Evironments Manual contains some examples of how to make synchronization
primitives with lwarx/stwcx.
Flying at a high speed
Having the courage
Getting over crisis
I rescue the people
Having the courage
Getting over crisis
I rescue the people
I think we can use it to build a patched version of other OS and loads PS3Linux with it... then ... we can try do some thinks on PS3Linux like run apps ... with support for full RSX... or use 256MB from RSX like RAM and have 512 MB for PS3Linux....
A patch for Linux kernel or Nvidia driver is a good way too... if we have a full system with wifi, bluetooth why do anothers drivers and others thinks?
Remember we can have a kboot with bluetooth and wifi drivers... with very little work....
A patch for Linux kernel or Nvidia driver is a good way too... if we have a full system with wifi, bluetooth why do anothers drivers and others thinks?
Remember we can have a kboot with bluetooth and wifi drivers... with very little work....
Anunakin
Exactly. The hardest thing I see about us making our own OS layer is SPU access, should be able to figure that out from the linux kernel though.mbf wrote:This is in no way a mean to bypass the hypervisor and hence will not allow full access to the RSX nor allow to use the RSX memory the same way as the XDR. This will only allow to load alternative OSes (anything other than linux that runs on PPC64) or even make a PS3 dedicated "Other" OS....
I think it's the most rational approach: pick up things from the kernel.Warren wrote:The hardest thing I see about us making our own OS layer is SPU access, should be able to figure that out from the linux kernel though.
However I am wondering if there is a license problem: IIRC the ps2dev env is under a MIT like license which is not compatible with the GPL (at least you can't put kernel source code under MIT).
Is it acceptable to have ps3dev under GPL license?
Personally, I'd say it's better not to.ldesnogu wrote:Is it acceptable to have ps3dev under GPL license?
I've been thinking about the implications of the Linux kernel being GPL for some time, and it really does make life complicated when trying to distribute software as binary. The boundary between software aggregation and derivative works becomes very confusing when shipping a bootable image containing a non-GPL program and a GPL kernel.
If there was an alternative to Linux then it would make life a lot easier, but OTOH it's an awful lot of effort to go to reimplement all the USB HID susbsytem, UDF drivers, etc. In some ways, reimplementing the PS3 stuff is the simplest because it all boils down to hypervisor calls at the end of the day.
No, releasing ps3dev under GPL is not acceptable.ldesnogu wrote:I think it's the most rational approach: pick up things from the kernel.Warren wrote:The hardest thing I see about us making our own OS layer is SPU access, should be able to figure that out from the linux kernel though.
However I am wondering if there is a license problem: IIRC the ps2dev env is under a MIT like license which is not compatible with the GPL (at least you can't put kernel source code under MIT).
Is it acceptable to have ps3dev under GPL license?
ps2sdk is AFL licensed and pspsdk is BSD licensed, I would very much like to continue this trend.
That said, doing so will cause problems with writing the abovementioned functionality (SPU, BT, USB, NET, WIFI). For the SPU side of things we might be able to get some docs / code from IBM that can be BSD licensed.
As for the others we may be able to find some appropriately licensed libraries out there or we might have to put a lot of work in before we have function parity with linux.