Subject: Re: RFC: Change SWI number base?
To: David Laight <David.Laight@btinternet.com>
From: Richard Earnshaw <rearnsha@arm.com>
List: port-arm
Date: 01/04/2002 13:45:21
You have to do the range checking anyway for both alternatives, so that's 
irrelevant to the argument.

> An alternative solution (for thumb) is to put the syscal number
> in the 16bit word following the 'swi 0' instruction.

The SWI field is 24 bits; and the bits Ben is talking about setting to 0xB 
for NetBSD are the top four of those.

>  The kernel then has
> to increment the user pc before returning from the SWI. Giving you:
> 
>     swi   0
>     .word SYS_foo
>     bcs   __cerror
>     mov   pc,lr

In thumb we couldn't guarantee the alignment of this.  Plus we really 
don't want data in the middle of the code stream, it's bad for cache 
accesses.  Constants need to be saved together, so that when cache lines 
are fetched they are normally all data or all code.

> 
> (except they are ARM insts, not thumb ones...)
> If you don't want to modify the user PC, reorder the instructions, eg:
> 
>     swi    0
>     movcc  pc,lr
>     b      __cerror
>     .word  SYS_foo

This would be truly horrible.  What about the IMB instructions which don't 
need to check for failure?  Now you need to branch around the constant...


In fact, the current arm32 kernel code currently handles the extraction of 
the SWI id field in the assembler stub:

ASENTRY_NP(swi_entry)
        PUSHFRAME

        sub     r0, lr, #0x00000004     /* Get the address of the SWI */
        ldr     r4, [r0]                /* Get the instruction */

        bic     r1, r4, #0xff000000     /* Extract the comment field */

        mov     r0, sp                  /* Pass the frame to any function 
*/

        bl      _C_LABEL(syscall)       /* It's a syscall ! */
	...

But this would be unsafe once we need to support thumb code, since we 
would have to test the PC first before trying to do the LDR (the PC may 
not be word aligned).  By switching the order of the parameters to syscall 
(and fixing PUSHFRAME to not clobber r0 -- we could use ip as the 
scratch), the sequence would simplify to

	PUSHFRAME

	mov	r1, sp
	bl	_C_LABEL(syscall)
	...

And in addition the code inside syscall would simplify as well, since we 
would no longer have to test for the call code being SYS_syscall.


I haven't thought about the following in detail, but it is possible that 
handling emulations for other OSes might be best done by changing the SWI 
vector in the system vectors table (something that could be done as part 
of a context switch).  Then the kernel would vector to the appropriate 
entry sequence for the current emulation and there would be no need to 
check what we were emulating before deciding how to extract the syscall 
code.  In fact, since the vectors are mapped into the "User address space" 
(though not user readable), we could have an appropriate page for each 
type of emulation and the cost of changing this at a context switch would 
be zero[1].

R.

[1] I was originally planning to add support in the kernels for using the 
high-vector mapping on those processors which support it (on the SA1100 
(note, not sa110), ARM9 and later, it is possible to map the vectors at VA 
0xffff0000).  Using this can make some things in the kernel simpler, since 
that is a natural kernel address.  However, the above idea would be more 
complex to implement if the vectors were up there...