::: Area #157 (comp.sys.acorn.programmer) Message: #40584 (Read 11 times, has 0 replies, 1308 bytes) Date : Sun Mar 21 19:26:24 1999 From : trill@netbook.demon.co.uk Subject: OS_CallASWI - how does it work? Message-ID: Is there any way I can directly call a SWI without the SWI instruction and without using OS_CallASWI? I've looked at the ARM datasheet, but it's of no real help. Ideally, I'd like a way to directly enter the ARM SWI vector with the SWI number I want to call passed to it: I'm sure I need to call OS_EnterOS, but I don't know how to communicate the SWI number I want to the SWI vector. I've tried disassembling addresses &8 and &3800008, but with no luck. I'm just interested in how to do this, rather than for any particular reason, so please don't scream about SVC code/other evils :) I'm really thinking about something like OS_CallASWI but without using that particular SWI - is there any source code available for this? -- Supporting Acorn Users North East (ACNE) Using an Acorn StrongARM RiscPC in a Wintel free zone We are John Cage of Borg. Assimilation troubles us; we have to take a moment. Poughkeepsie. --- EchoMaker 0.49 # Origin: Trills and Technologies * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2) ::: Area #157 (comp.sys.acorn.programmer) Message: #40585 (Read 11 times, has 0 replies, 1828 bytes) Date : Sun Mar 21 23:43:18 1999 From : kade_fh@postoffice.utas.edu.au Subject: Re: OS_CallASWI - how does it work? Message-ID: <36F58405.C0B49342@postoffice.utas.edu.au> James MacDonald wrote: > > Is there any way I can directly call a SWI without the > SWI instruction and without using OS_CallASWI? I've looked > at the ARM datasheet, but it's of no real help. > > Ideally, I'd like a way to directly enter the ARM SWI vector > with the SWI number I want to call passed to it: I'm sure I > need to call OS_EnterOS, but I don't know how to communicate > the SWI number I want to the SWI vector. I've tried disassembling > addresses &8 and &3800008, but with no luck. I'm just interested > in how to do this, rather than for any particular reason, so > please don't scream about SVC code/other evils :) It seems to me there's no point, if I understand what you mean correctly. When you execute a SWI instruction, you branch (with link) to the SWI vector. The SWI number has to be read out of the instruction which is at the location (pipeline corrected) in R14. The OS then has a jumptable for kernel SWIs, or works out which module owns the SWI, and jumps into its handler code. Writing your own code to do this is non-trivial. CallASWI (at least in pre SA versions), IIRC, usually uses self-modifying code. It is probably also possible to do it by writing an appropriate wrapper before branching somewhere into the OS (kernel dispatch table, or earlier for module SWIs). You'd need to work out the register bindings, however, and you couldn't be sure if these would change from OS to OS. --- EchoMaker 0.49 # Origin: Another Optus Customer * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2) ::: Area #157 (comp.sys.acorn.programmer) Message: #40610 (Read 11 times, has 0 replies, 2468 bytes) Date : Mon Mar 22 19:26:42 1999 From : trill@netbook.demon.co.uk Subject: Re: OS_CallASWI - how does it work? Message-ID: In message <7d45it$m97$1@inkvine.fluff.org> Chris Rutter wrote: [OS_CallASWI replacement) >Yes; try in `Libs.Core' (or somesuch, I can't remember exactly) in >the Straylight Source Release; you might only need `core.zip', in fact. >Fetch it from . OK, thanks. Based on the SSR I've put together this snippet of code. It's ARM code from hell (SA kludges and SVC mode), but it works. Sorry about the tabulation, if it messes up your newsreader: ADR R0, string1 ;To write with kludge MOV R10, #2 ;OS_Write0 BL build B properswi .string1 DCB "Printed using code building, ",0 ALIGN .string2 DCB "and now with a proper SWI instruction.",0 ALIGN .properswi ADR R0, string2 SWI OS_Write0 SWI OS_Exit .retR12 MOV PC, R12 .build SWI OS_EnterOS ;Evil! Evil! :-) BIC R10,R10,#&FF000000 ;Clear the opcode byte ORR R10,R10,#&EF000000 ;And make it SWIAL LDR R14,retR12 ;And load the return instr STMFD R13!,{R10,R14} ;Save code on the stack SWI XOS_SynchroniseCodeAreas ; Again, an awful kludge MOV R12,PC ;Set up return address MOV PC,R13 ;And call the code ADD R13,R13,#8 ;Reclaim stack space TEQP R15, #0 ;Back to user mode MOV PC, R14 ;Return from BL -- Supporting Acorn Users North East (ACNE) Using an Acorn StrongARM RiscPC in a Wintel free zone We are John Cage of Borg. Assimilation troubles us; we have to take a moment. Poughkeepsie. --- EchoMaker 0.49 # Origin: Trills and Technologies * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2) ::: Area #157 (comp.sys.acorn.programmer) Message: #40618 (Read 11 times, has 0 replies, 1248 bytes) Date : Tue Mar 23 09:47:03 1999 From : marko.lukat@tao-group.com Subject: Re: OS_CallASWI - how does it work? Message-ID: <36F76317.6EC1EA4D@tao-group.com> James MacDonald wrote: [..] > > In message <7d45it$m97$1@inkvine.fluff.org> > Chris Rutter wrote: > > [OS_CallASWI replacement) > > >Yes; try in `Libs.Core' (or somesuch, I can't remember exactly) in > >the Straylight Source Release; you might only need `core.zip', in fact. > >Fetch it from . > > OK, thanks. Based on the SSR I've put together this snippet > of code. It's ARM code from hell (SA kludges and SVC mode), > but it works. Sorry about the tabulation, if it messes up > your newsreader: > [code] Erm, what about MOV R0,#SWInumber ORR R0,R0,#&EF000000 STR R0,patch .patch SWI 0 or similar? Since the SWI code as such determines the SWI number by doing an LDR rx,[lk,#-4] you don't even have to synchronize the modified location. Cheers, Marko --- EchoMaker 0.49 # Origin: Tao * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2) ::: Area #157 (comp.sys.acorn.programmer) Message: #40620 (Read 11 times, has 0 replies, 1292 bytes) Date : Tue Mar 23 09:58:38 1999 From : paul@interconnex.co.uk Subject: Re: OS_CallASWI - how does it work? Message-ID: In article , James MacDonald wrote: > ADR R0, string1 ;To write with kludge > MOV R10, #2 ;OS_Write0 > BL build [snip] > .build [snip] > SWI XOS_SynchroniseCodeAreas ; Again, an awful kludge Erk! If my reading of this is correct, you're calling XOS_SyncCode... with r0=. Remember that bit 0 of r0 is important when calling that swi - if it's 0 then it will sync the *whole* cache (takes a long time). If it's 1 then it will sync between r1 and r2. Basically this code will only work if string1 is word aligned (or half-word aligned). Beware. Paul. -- Interconnex UK Ltd Box Bush Farm, West Wick, W-s-M, BS24 7TF. Tel & Fax: (01934) 522880. mailto:paul@interconnex.co.uk http://www.interconnex.co.uk/ --- EchoMaker 0.49 # Origin: Interconnex UK Ltd * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2) ::: Area #157 (comp.sys.acorn.programmer) Message: #40664 (Read 7 times, has 0 replies, 2748 bytes) Date : Sat Mar 27 14:36:08 1999 From : JamesSutherland@gmx.de Subject: Re: OS_CallASWI - how does it work? Message-ID: On Tue, 23 Mar 1999 09:47:03 +0000, Marko Lukat wrote: >James MacDonald wrote: >[..] >> >> In message <7d45it$m97$1@inkvine.fluff.org> >> Chris Rutter wrote: >> >> [OS_CallASWI replacement) >> >> >Yes; try in `Libs.Core' (or somesuch, I can't remember exactly) in >> >the Straylight Source Release; you might only need `core.zip', in fact. >> >Fetch it from . >> >> OK, thanks. Based on the SSR I've put together this snippet >> of code. It's ARM code from hell (SA kludges and SVC mode), >> but it works. Sorry about the tabulation, if it messes up >> your newsreader: >> >[code] > >Erm, what about > > MOV R0,#SWInumber > ORR R0,R0,#&EF000000 > STR R0,patch >.patch > SWI 0 > >or similar? Since the SWI code as such determines the SWI number by >doing an LDR rx,[lk,#-4] you don't even have to synchronize the >modified location. That's the key here. You don't need to build and execute your own SWI xxx instruction, you can call the SWI handler directly. You need to be in SVC mode (OS_EnterOS), then basically call the code for a SWI handler. So long as you set up R14 manually, rather than using BL to save it automatically, you're fine. SWI OS_EnterOS ; Enter SVC mode ADR R14, cont ; Faked return address STR R12, [R14,#-4] ; Store the SWI number B &8 ; Jump (WITHOUT link) into the SWI handler EQUD 0 ; Dummy SWI call - never executed .cont SUB R15, #3 ; Clear bits 0 and 1 (change from SVC->USR) Basically, you just set up a `fake' return address, making it look as if the SWI instruction is executing. In reality, though, that instruction is NEVER executed (it just looks that way) - that word is really only used as data. You probably don't even need to set the top word to be &EF, since I doubt the SWI handler checks that. Because no code is ever modified, you do not need to flush any caches; the only flaw is that I set the CPU back to USR mode by hacking R15 directly, which won't work in 32-bit mode. On the other hand, nor will the SWI call itself, so that's academic (for the time being). > >Cheers, >Marko -- James A Sutherland 20 Young St, Perth PH2 0EF, UK Tel. +44 1738 443515 --- EchoMaker 0.49 # Origin: Customer of Planet Online * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2) ::: Area #157 (comp.sys.acorn.programmer) Message: #40665 (Read 7 times, has 0 replies, 3456 bytes) Date : Sat Mar 27 15:00:59 1999 From : dickon-news@fluff.org Subject: Re: OS_CallASWI - how does it work? Message-ID: <43568e948%dickon-news@splurge.fluff.org> In message JamesSutherland@gmx.de (root) wrote: : That's the key here. You don't need to build and execute your own SWI xxx : instruction, you can call the SWI handler directly. But why? There's no point, and creating the instruction is easier anyway. : You need to be in SVC mode (OS_EnterOS), then basically call the code : for a SWI handler. So long as you set up R14 manually, rather than : using BL to save it automatically, you're fine. : SWI OS_EnterOS ; Enter SVC mode : ADR R14, cont ; Faked return address : STR R12, [R14,#-4] ; Store the SWI number : B &8 ; Jump (WITHOUT link) into the SWI handler : EQUD 0 ; Dummy SWI call - never executed : .cont : SUB R15, #3 ; Clear bits 0 and 1 (change from SVC->USR) If the SWI (or the handler; I'm not 100% sure which) returned setting the flags, you'll be in user mode *anyway*; you forgot to set the bottom two bits of the returned r14 (favourite gotcha of a number of people (I'm usually pretty good, but I found one lurking this afternoon...)). Some problems with the above: * Subtracting three from r15 is a stupid thing to do anyway as you skip the next instruction or two (I forget which). * As you forgot to set the S flag on the sub instruction, nothing would have happened. * That code is not relocatable. You have to assemble that at the address you wish to use it. * It only works in user mode. * You'd completely screw the processor flags. And that's just the list of things I thought whilst writing this. I'm sure that given time I could probably think up a few more cases where it fails; in short, a sick, evil and broken piece of code. : Basically, you just set up a `fake' return address, making it look as if : the SWI instruction is executing. In reality, though, that instruction is : NEVER executed (it just looks that way) - that word is really only used as : data. You probably don't even need to set the top word to be &EF, since I : doubt the SWI handler checks that. : Because no code is ever modified, you do not need to flush any caches; the : only flaw is that I set the CPU back to USR mode by hacking R15 directly, : which won't work in 32-bit mode. On the other hand, nor will the SWI call : itself, so that's academic (for the time being). I suggest the following (SWI number in r10 (I use r12 for workspace too much)). This is very similar (if not identical) to the code that someone's already posted here: callaswi stmfd r13!, {r14} orr r14, r10, #&ef000000 str r14, swi_inst swi_inst swi 0x0 ldmfd r13!, {pc} No caches need to be flushed as the SWI instruction is already a SWI (so the instruction cache sees the SWI, but the data cache sees the 'proper' SWI). -- Dickon Hood Due to binaries posted to non-binary newsgroups, my .sig is temporarily unavailable. Normal service will be resumed as soon as possible. We apologise for the inconvenience in the mean time. --- EchoMaker 0.49 # Origin: the Fluff Disorganisation * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2) ::: Area #157 (comp.sys.acorn.programmer) Message: #40671 (Read 6 times, has 0 replies, 6316 bytes) Date : Sun Mar 28 02:00:00 1999 From : news@youmustbejoking.demon.com.uk Subject: Re: OS_CallASWI - how does it work? Message-ID: <48E99F0C40%news@youmustbejoking.demon.com.uk> In message <36fd617d.4721078@195.92.193.11> JamesSutherland@gmx.net (James Sutherland) wrote: > On Sat, 27 Mar 1999 15:00:59 +0000, Dickon Hood > wrote: >> In message >> JamesSutherland@gmx.de (root) wrote: >>> That's the key here. You don't need to build and execute your own SWI xxx >>> instruction, you can call the SWI handler directly. >> But why? There's no point, and creating the instruction is easier anyway. > But `creating the instruction' is self-modifying code True... > - executing code like that is very bad. One advantage of my approach is it > could be run from ROM (just put the 12 bytes around the `.cont' into > workspace) without changes. You would probably get upset if/when the code > area is write protected. You only need three instructions: SWI 0 LDR PC,[PC,#-4] DCD return_address >>> You need to be in SVC mode (OS_EnterOS), then basically call the code for >>> a SWI handler. So long as you set up R14 manually, rather than using BL >>> to save it automatically, you're fine. >>> SWI OS_EnterOS ; Enter SVC mode >>> ADR R14, cont ; Faked return address >>> STR R12, [R14,#-4] ; Store the SWI number >>> B &8 ; Jump (WITHOUT link) into the SWI handler >>> EQUD 0 ; Dummy SWI call - never executed >>> .cont >>> SUB R15, R15, #3 ; Clear bits 0 and 1 (change from SVC->USR) [corrected error in SUB instruction] >> If the SWI (or the handler; I'm not 100% sure which) returned setting the >> flags, you'll be in user mode *anyway*; > No. I will be in user mode anyway, whatever was returned. The SUB on the > end should have been something like MOV R15, R14. Without having earlier preserved R14? >> you forgot to set the bottom two bits of the returned r14 (favourite >> gotcha of a number of people (I'm usually pretty good, but I found one >> lurking this afternoon...)). > `Forgot'? Did I really want to be returned to in SVC mode? I hope not. You would if you called that code when already in SVC mode. >> Some problems with the above: >> * Subtracting three from r15 is a stupid thing to do anyway as you skip >> the next instruction or two (I forget which). > OK, it should have been either 7 or 11. Best to avoid the SUB altogether. >> * As you forgot to set the S flag on the sub instruction, nothing would >> have happened. > Oh dear. I'm heart-broken. TBH, I wouldn't want to modify R15 directly > anyway, I'd want to modify the PSR. Let the OS handle it :-) >> * That code is not relocatable. You have to assemble that at the >> address you wish to use it. > Why? The ADR should use a PC-relative calculation. But the B instruction isn't relocatable; you should have used MOV PC,#8 >> * It only works in user mode. > No, it only works in SVC mode, hence the call to OS_EnterOS at the > beginning. But it always returns to USR mode, which as I said above... >> * You'd completely screw the processor flags. > Which aren't supposed to be preserved anyway, now. Well... you do need to preserve the flags as returned from the SWI; the calling code will probably want to test them. >> And that's just the list of things I thought whilst writing this. I'm >> sure that given time I could probably think up a few more cases where it >> fails; in short, a sick, evil and broken piece of code. > Sick? No. > Evil? Not really. It isn't self-modifying, and it is ROMmable. > Broken? No. Broken? Yes. > It was an example of the principle, not production code. Allegedly. ;-) [snip] >> I suggest the following (SWI number in r10 (I use r12 for workspace too >> much)). This is very similar (if not identical) to the code that >> someone's already posted here: >> callaswi >> stmfd r13!, {r14} >> orr r14, r10, #&ef000000 >> str r14, swi_inst >> swi_inst >> swi 0x0 >> ldmfd r13!, {pc} >> No caches need to be flushed as the SWI instruction is already a SWI (so >> the instruction cache sees the SWI, but the data cache sees the 'proper' >> SWI). > But that's self-modifying code, which really is sick, evil and broken > programming. It's OK when in RAM, and as Dickon says, it's OK on a StrongARM. > Deliberately breaking cache coherency isn't a good idea. It does this, yes, but since the instruction in the Icache is always a valid SWI, and since to find out /which/ SWI is called, an LDR is needed, there's no problem. > It would cause a cache flush under most systems (a crash under others) > since you are modifying actual executable code; mine doesn't if you > position the .cont properly. Irrelevant. From ROM, you want something like this: init STMFD r13!,{r14} LDR r1,swi_ptr LDR r2,call STR r2,[r1] MOV r2,#&EF000000 STR r2,[r1,#4] LDR r2,ret STR r2,[r1,#8] MOV r0,#0 ADD r2,r1,#4 SWI XOS_SynchroniseCodeAreas LDMFD r13!,{pc}^ swi_ptr DCD some_protected_address_in_RAM ; we need three words call STMFD r13!,{r14} ret LDMFD r13!,{pc} callaswi STMFD r13!,{r10,r14} BIC r10,r10,#&FF000000 ORR r10,r10,#&EF000000 LDR r14,swi_ptr STR r10,[r14,#4] BL callaswi_jump LDMFD r13!,{r10,pc} callaswi_jump LDR pc,swi_ptr Untested, and it's an example of the principle, not production code ;-) -- | Darren Salt | Acorn | nr. Ashington, | ds@youmustbejoking,demon,co,uk | Risc PC, Spec +3, | Club | Northumberland | ds@zap,uk,eu,org ** anti-UCE | A3010, BBC M128 | NE | Toon Army | arcsalt@spuddy,mew,co,uk | Z80Em and 6502Em Support Packs. AY sound support. View your problem closely enough and you'll recognise yourself as part of it. --- EchoMaker 0.49 * Origin: The Arcade BBS Usenet News Gateway (2:254/27.2)