Sony have implemented this so that applications are executing in user mode,
and it seems they have denied the usage of the coprocessor instructions MRS
and MSR when in user mode. I need to use these instructions - and hence I
need to switch to supervisor mode.
Have someone here seen this before and have a solution?
The CPU switches to supervisor mode when a SWI [ software interrupt ]
instruction is executed, but setting up this instruction seems like a *huge*
task.
So in short, this is what I want to do:
1. Enter supervisor mode.
2. Continue execution in my code that executes coprocessor instructions.
3. Return to user mode and return execution where I left it before entering
supervisor mode.
If anyone have any ideas or suggestions, please let me know.
TIA =)
Jonatan Fernstad
The instructions are not 'denied', they can be used un user mode to set the
PSR flag bits. However no ARM chip allows the processor to be switched from
user mode to a privileged via an MSR, as this would completely invalidate
any process protection implemented by the operating system.
The only way to switch out of user mode is to cause an exception which
results in the processor switching to a privileged mode in order to service
it via the hardware vectors. The normal way is to use a SWI (software
interrupt) instruction either directly or via an OS API, however it is
entirely up to the operating system whether implement this facility or grant
permission to a particular task.
---druck
--
The ARM Club Free Software - http://www.armclub.org.uk/free/
The 32bit Conversions Page - http://www.quantumsoft.co.uk/druck/
I found a typo in my post: the instructions that can not be executed in user
mode are MCR and MRC - not MRS and MSR.
MCR and MRC are used to read and write to the coprocessor registers. And it
seems sony have denied access to these instructions in user mode.
> The only way to switch out of user mode is to cause an exception which
> results in the processor switching to a privileged mode in order to
service
> it via the hardware vectors. The normal way is to use a SWI (software
> interrupt) instruction either directly or via an OS API.
Then this is what I need to do. Have you done this yourself directly?
Setting this up and controlling where execution continues after the SWI
instruction seems quite hard to do.
If anyone have any suggestions on how to do this, I would appreciate it. =)
/Jonatan
> MCR and MRC are used to read and write to the coprocessor registers. And
> it seems sony have denied access to these instructions in user mode.
I don't think you can deny access to intructions. You CAN deny access to
memory though.
> > The normal way is to use a SWI
>
> Then this is what I need to do. Have you done this yourself directly?
> Setting this up and controlling where execution continues after the SWI
> instruction seems quite hard to do.
It is easy, as long as the OS doesn't protect the first physical page of
memory where the exception vectors are. Of course, most OSes DO protect this
memory from user mode writes - so you won't be able to change it - Catch 22.
As Druck implied, this isn't something you can force on an OS that wants you
to stay in user mode.
> If anyone have any suggestions on how to do this, I would appreciate it.
You will have to ask in a Palm OS group, I think.
--
Nemo ne...@20000.org
I believe coprocessors can deny access to operations based on the processor
mode otherwise any user could do nasty things with the system coprocessor.
Control of this would be up to the individual coprocessor.
Graeme
Jonatan, can you write into the memory region containing the vector table?
If not, you're stuck :(
But if you can, you can insert your own mini-SWI handler before the
"official"
SWI handler. Your SWI handler will deal with only your new SWI number,
and fall through to the official SWI handler for any SWI's it doesnt
recognise.
You'll need to:
1) read the current SWI vector instruction, decode the destination address
and save it away somewhere,
2) replace the SWI vector instruction with one that branches to your mini
SWI handler.
Then in your mini-SWI handler:
1) Save all registers you are going to use in your mini-SWI handler
2) Read the SWI instruction (at LR-4 if it was an ARM instruction,
LR-2 if it was a Thumb instruction... check the T bit in SPSR to
see which it was).
3) Extract the SWI number
4) See if its your new JONATANS_SWI number, if so handle it
and return using an LDMFD SP!, {reg list, PC}^ to get back
to user mode...
if not, restore registers and branch to the original SWI handler.
SWI VECTOR INSTRUCTION:
You'll need to remember the address of the original SWI handler, so you
can restore registers and branch to it, if need be. Remember not to
corrupt registers 0 to 3, as these are often used to hold SWI function
arguments.
The technique you use depends on the instruction currently in
the SWI vector. It'll probably be either:
LDR PC, [PC, #offset] or
B addr or
MOV PC, #addr
The easiest one to deal with is LDR PC - just put the address of your
mini-SWI
handler into the location from which the ARM is reading the address of the
real
SWI handler.
B addr is more complicated - the address has to be within 32MByte of the
instruction, and is encoded as:
(destination address - (address of B instruction + 8)) >> 2
The offset of 8 is because this is a PC relative branch and due to
pipelining,
the PC is always pointing the instruction being fetched, 2 beyond the one
being executed.
MOV PC, #addr is very unlikely to be seen, the address has to fit in ARM's
rather arcane immediate constant rules... let's not go there right now.
I'm sure there must be an app note on ARM's website showing how to do
this - its certainly in the Training Course material - I just can't find it
at the
moment.
Peter.
I am not absolutely sure where in memory the vector table is.
I am assuming that this is somewhere in RAM, and the vector table is
populated by the OS upon reset?
How does the processor know where to continue execution after the swi
instruction?
I have seen the vector table address been defined as
unsigned long * swi = (unsigned long *) 0x08
is this where it *should* be?
Thanks for your post Peter, it was very informative. Now, if I just can find
out where the execution continues after the swi, and I am allowed to write
to this memory address I think it will work. :]
/Jonatan
For complete and accurate details, consult the processor reference manual
(PRM).
USUALLY, an SWI instruction does some variation along the theme of pushing
the PC on the stack, then fetching the new PC value from the SWI vector
location. It may be a subroutine call equivalent, or it may be an interrupt
equivalent. Depending on the processor architecture, it may switch to
executive mode, or it may not. When the SWI handler is finished, it returns
to the code that executed the SWI instruction.
YMMV. RTFPRM.
> > Jonatan, can you write into the memory region containing the vector table?
> > If not, you're stuck :(
>
> I am not absolutely sure where in memory the vector table is.
> I am assuming that this is somewhere in RAM, and the vector table is
> populated by the OS upon reset?
The vector table is usually at address 0, or can be at the top of memory if
high vectors are set. Refer to your ARM data sheet for details. The normal
way of working is to map the system ROM in to address 0 on reset to give
the default reset vector, then replace it with RAM when the boot strap code
has finished).
> How does the processor know where to continue execution after the swi
> instruction?
R14_SVC will be set up to the return address, allowing a MOVS PC,R14 to
return assuming you are the actual owner of the vector, and not being
called from an OS wrapper.
> I have seen the vector table address been defined as
>
> unsigned long * swi = (unsigned long *) 0x08
>
> is this where it *should* be?
That is the SWI entry in the hardware vectors.
> Thanks for your post Peter, it was very informative. Now, if I just can
> find out where the execution continues after the swi, and I am allowed to
> write to this memory address I think it will work. :]
It is unlikely a user mode program will be allowed to write to the vectors,
as any OS worth its salts will protect these against accidental corruption
(writing through NULL pointers) and malicious code promoting itself to have
system privs.
I think you need to study the ARM Architecture Reference Manual before
pursuing this.
The ARM vector table is located at physical address 0 (on powerup).
This MUST be ROM (on powerup) because the first vector - not really a
"vector" BTW, it's an actual instruction - is the POR vector. During
POI, the processor will *probably* set up a RAM-based vector table and
configure the MMU and/or memory banking hardware so that logical
address 0 will be translated to wherever the RAM-based table was
placed.
If the OS vendor has gone to the trouble of insulating user from
supervisor code, then it's a pretty safe bet you won't be able to
write the vector area from user mode.
The XScale Microarchitecture does include a "coprocessor access register" (in
CP14) which allows operating systems to grant/deny access to coprocessors.
However, that is on top of any access control done by the coprocessor itself.
It also only controls access to CP0 thru' CP13. CP14 and CP15 can only ever
be accessed from a privileged mode (such as supervisor).
If your problem is, for instance, that you cannot access CP0 (the 40-bit
accumulator) then this would be down to the way the operating system is
programming this register. The intent is presumably to save time on context
switching, although I don't know enough (anything) about PalmOS to be able to
comment. I wouldn't know, for example, whether this is down to the operating
system or some specific OEM port.
Mike.
--
Michael Williams Tel: +44 1223 400400
Senior Engineer Web: http://www.arm.com/
Development Systems, ARM Limited, 110 Fulbourn Road, Cambridge, CB1 9NJ, UK
This message is intended for the addressee(s) only and may contain
information that is the property of, and/or subject to a confidentiality
agreement between the intended recipient(s), their organisation and/or the
ARM Group of Companies. If you are not an intended recipient of this
message, you should not read, copy, forward or otherwise distribute or
further disclose the information in it; misuse of the contents of this
message may violate various laws in your state, jurisdiction or
country. If you have received this message in error, please contact
the originator of this message via email and delete all copies of
this message from your computer or network, thank you.
Could it be placed "anywhere" or are those the only options?
> > How does the processor know where to continue execution after the swi
> > instruction?
What I meant with this question was: when the processor encounters a swi
instruction it continues execution at the vector table base address +#8. But
how does the processor know where in memory the vector table have been put?
Is this information stored in a register? In the ADS Developer guide they
dont talk much about the exact location of the vector table, or they are
implying that it is always at adress 0x0.
The 16 MB RAM in my device is split up in two parts.
Part 1 starts at memory location 0x0010000 and ends at 0x004FFFFF. This part
is not used for storage but for temporary buffers, heap etc.
Part 2 starts at memory location 0x00500110 and is the remaining ~ 11 Mb.
This part is used for "permanent" storage.
I have not been able to locate the vector table when inspecting memory.
Possible locations would perhaps be 0x00000000, 0x00100000, 0x00500000 or
0x00500110, but it doesnt seem any of these are correct.
> It is unlikely a user mode program will be allowed to write to the
vectors,
>as any OS worth its salts will protect these against accidental corruption
> (writing through NULL pointers) and malicious code promoting itself to
have
> system privs.
One might hope that they did not add this limitation. I guess I will find
out if I find the location of the vector table.
I have been able to write to every adress in RAM sofar, except the four
bytes at the start of 0x0, but these are always 0 anyway.
On many ARM cores, the options are 0x0 and 0xFFFF0000. These are virtual
addresses (so physical when the MMU is disabled, e.g. at reset).
The table is by default at 0x0. Remapping to 0xFFFF0000 is done by writing to
the V flag in the CP15 control register. Some processor cores allow boot from
0xFFFF0000 through an external input, but you have to check your processor's
datasheet for this. And even if the core allows it, that doesn't necessarily
mean the device containing the core does.
If you map ROM at zero and RAM at 0xFFFF0000 then it is quite simple to boot
from the ROM, set up the RAM with the "run-time" vectors and set the V bit to
switch over.
Some ARM cores, however, do not support remapping the vector table to
0xFFFF0000. Again, you have to check the individual core datasheet for
details. In general, those modern cores with caches do support it, older
cores and uncached cores do not, but this is just a general rule and there
are probably exceptions.
Hope that answers your question,