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...