gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > SWI troubles :-(

#122548 - SpacedCowboy - Tue Mar 20, 2007 4:45 am

Is there anything "special" about an SWI - are there any registers I have to set to enable them (can't see *why*, but it doesn't hurt to ask :-) or any other hoops to jump through ?

I've been playing around with the source of Mighty-Max's virt-16 OS. I wanted to change a few things (a single namespace of OS_(whatever); to locate it in the bottom 512k of WRAM so I have more space eg: for a wifi device-driver or proper ELF loader; to use the 'r20' FAT library so my DS-X works; and to add a pthreads layer over the threading facilities, so I can have mutexes/semaphores).

I've got some problem code, where I'm calling 'syscall' which was defined as:
Code:

/******************************************************************************\
|* Generic syscall handler. Takes either 0,1,2 or 3 arguments
\******************************************************************************/
OS_syscall:
OS_syscall1:
OS_syscall2:
OS_syscall3:
   swi 0x00               // Call the handler set up in the BIOS
   BX lr                   // then return


... but has now turned into:

Code:

/******************************************************************************\
|* Generic syscall handler. Takes either 0,1,2 or 3 arguments
\******************************************************************************/
OS_syscall:
OS_syscall1:
OS_syscall2:
OS_syscall3:
   
   stmdb    r13!, {r0-r3}        // Store the registers
   
   bl       OS_cpreg
   mov      r2, r0               // r2 <= CP15 reg value
   mov      r0, #0
   mov      r1, #100
   ldr      r3, =OS_GFX_printX32
   bl       _call_via_r3         // print it
   
   mov      r2,   #0x08          // r2 <= SWI register value
   ldr      r2, [r2]
   mov      r0, #0
   mov      r1, #113
   ldr      r3, =OS_GFX_printX32
   bl       _call_via_r3         // print it
   
   ldr      r2,   =OS_codeSWI    // r2 <= 1st insn in SWI routine
   ldr      r2, [r2]
   mov      r0, #0
   mov      r1, #126
   ldr      r3, =OS_GFX_printX32
   bl       _call_via_r3         // print it
   
   ldr      r1,  =0x06016c1E     // blue dot at (15,182)
   ldr      r2,  =0xfc00
   strh     r2,[r1]
   ldmia    r13!, {r0-r3}        // Restore the registers
   
   swi 0x00                      // Call the handler set up in the BIOS
   BX lr                         // then return



... because the code in my SWI just isn't being called. The expanded 'syscall' routine fetches (at the time just before I call 'swi') register 1 of the CP15 chip, and prints it out, then fetches the contents of the SWI vector (a branch instruction), and prints that, then fetches the contents of the memory address that branch points at, and prints that out. It then plots a blue pixel (this works) and finally calls the SWI as planned

All of the printed-out numbers seem perfectly ok...

- the CP15 register(1) has the value 0x0005107D, so the 'V' bit is clear, meaning the exception jump-table is at 0x00000000 rather than 0xffff0000. So that's good.

- the value at 0x00000008 is 0xEA000007, which is a branch-always to +7 words, and my routine (OS_codeSWI) is 9 words away from the branch instruction. Given the PC offset of 2 words, this seems pretty peachy.

- the value at 0x0000002C (= OS_codeSWI) is 0xE92D5FFF, which is the bit-vector for the "stmdb r13!, {r0-r12,r14}" instruction, which is the first statement of the code at the address OS_codeSWI.

The first thing the SWI routine does (after storing the registers on the stack) is plot a *red* pixel close to the blue one. Unfortunately the red pixel never appears :-(

So, I'm struggling to understand how (when it all seems set up ok), the code in the SWI is never jumped-to. Max was (is :-) using regions to define what addresses can be accessed, so it occured to me that maybe a fault was happening when the SWI instruction was executed, but according to Steve Furber ("Arm System-on-a-chip architecture, 2nd edition"), the SWI process is:

- save the address of the insn after the SWI in r14_svc
- save CPSR in SPSR_svc
- Enter supervisor mode, disable IRQ (not FIQ)
- Set PC to 0x08 and begin executing

... so the system mode ought to be privileged by the time it tries to read address 0x08, and the current state of the protection registers is:

Code:

   OS_MPU_writeProtectionBase0(0x0000003F) ;
   OS_MPU_writeDataPermissions(0x33333331) ;      
   OS_MPU_writeCodePermissions(0x33333331) ;


... meaning that region 0 is enabled for the entire address range (0-4GB), and access is granted to system-modes. So it ought to be ok. Just in case, I modified the permissions to 0x33333333 instead, but I still had the problem.

I moved the pageAddress array of swappable pages to start at 0x02080000 instead of 0x02000000, so I have the first 512k to play with - I oughn't be being swapped out :-) It's not allocating much memory yet anyway - the 'memStatistics' call show both TCM and WRAM still have plenty of space in them...

So, Im not having much luck solving this - if anyone has a clue as to why it might not be working, I'd love to hear it :-) Full source available if that'll help...

Cheers,
Simon.

#122555 - HyperHacker - Tue Mar 20, 2007 7:00 am

Does it work if you call the SWI routine yourself instead of using an SWI instruction? I understand some trickery had to be used so that the OS's SWIs were called rather than the ones in the BIOS; perhaps you've broken this.
_________________
I'm a PSP hacker now, but I still <3 DS.

#122558 - SpacedCowboy - Tue Mar 20, 2007 7:12 am

Perhaps I have - I noticed that Max was using a different 'specs' file (that I don't have) for compiling his kernel. I'll PM him and ask him what that was for :)

In the mean-time, I've uploaded the source in case anyone wants to look at it (hey, you can't fault a man for trying [grin])

Simon

#123011 - Mighty Max - Sat Mar 24, 2007 2:20 pm

Sorry, for responding that late.

The specs were modified because i load the the system mode code (.knl) into the shared wram at 0x3000000 so that this code was needed to compile to reside at that place instead of the 0x2000000 base.

For tracking down your problem i recomment starting it in desmume.

I allways used to insert a halt (label: b label) and check whether desmume showed the expected register contents when it reaches this label.

But I think GPF has released a gdb-enabled version of desmume somewhere since, which makes it more easy to track the error down.
_________________
GBAMP Multiboot